Сузить тип поля Java, не делая обобщающий класс универсальным? - PullRequest
1 голос
/ 28 марта 2009

Можно ли сузить тип поля в классе Java, не делая сам содержащий класс универсальным?

Общий пример будет выглядеть примерно так:

abstract class MyClass {
    //...
}

interface MyInterface {
    //...
}

class MyConcreteClass<T extends MyClass & MyInterface> {
    private T value;
}

Есть ли способ сделать следующее:

class MyConcreteClass {
    private MyClass & MyInterface value;
}

Это по сути эквивалентно MyConcreteClass или необработанному типу MyConcreteClass. В моей реализации параметр типа будет изменяться в течение срока службы объекта (проклятая изменчивость! Он наложен на меня JPA!), Поэтому аннотация типа кажется несколько излишней.

  • РЕДАКТИРОВАТЬ -

Есть еще одно ограничение, о котором я забыл упомянуть. У нас также будет это:

class SubA extends MyClass
class SubB extends MyClass
class SubC extends MyClass

class SubSubA extends SubA implements MyInterface
class SubSubB extends SubB implements MyInterface
class SubSubC extends SubC implements MyInterface

Таким образом, простое объявление абстрактного подкласса MyClass, реализующего MyInterface, не является подходящим решением.

Кроме того, конечный тип поля должен быть конкретным типом, а не просто интерфейсом, представляющим пересечение, по той простой причине, что на сохраняемые JPA объекты не могут ссылаться их типы интерфейса. То есть постоянное поле в классе сущности JPA должно иметь тип примитива или конкретный тип сущности.

Ответы [ 3 ]

2 голосов
/ 28 марта 2009

Я никогда не сталкивался с подобной проблемой (и поэтому не приходит в голову элегантное решение: -) ... однако ...

interface Fooable 
{
}

abstract class MyClass 
    implements Fooable 
{
}

interface MyInterface 
    extends Fooable 
{
}

class MyConcreteClass 
{
    private Fooable value;
}
1 голос
/ 28 марта 2009

В таких сложных случаях вы должны скрывать классы за интерфейсами.

Затем вы можете определить явный интерфейс для пересечения, то есть интерфейс, который расширяет и интерфейс, соответствующий MyClass и MyInterface, и позволяя соответствующим суперклассам реализовать его вместо MyInterface.

0 голосов
/ 28 марта 2009

Я не думаю, что есть способ сделать это. Во всяком случае, не совсем так. Однако, поскольку это частное поле и вы полностью им управляете, вы можете просто объявить его как

 private MyClass value;

, но также убедитесь, что во всем вашем коде к нему относятся только объекты, реализующие MyInterface, и приводите его везде, где вам нужно получить к нему доступ в качестве интерфейса. Да, выглядит грязно, и это (немного).

Вы также можете создать следующий производный класс

abstract class MyDerivedClass extends MyClass implements MyInterface {
    //...
}

и затем используйте

 private MyDerivedClass value;

Это намного чище, но вы должны создать другой класс, просто для этой цели ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...