2014-06-12 4 views
4

У меня есть базовый универсальный класс, представляющий все объекты моей модели, которые имеют идентификатор любого типа:Java общий класс другого обобщенного класса

public abstract class IdObject<T> { 
    private T id; 
    public T getId()  { return this.id; } 
    public void setId(T id) { this.id = id; } 
} 

Тогда у меня есть супер-интерфейс, представляющий DAO для тех, IdObject объекты:

public interface IdObjectDAO<T extends IdObject<U>> { 
    public T getObjectById(U id); 
} 

но я получаю ошибку компиляции из «U не может быть разрешен к типу». Если изменить определение интерфейса с помощью:

public interface IdObjectDAO<T extends IdObject<U extends Object>> {...} 

Я получаю ошибку компиляции из «ошибок синтаксиса на знак„продолжается“,, как ожидается». Единственный способ определить интерфейс без ошибок компилятора:

public interface IdObjectDAO<T extends IdObject<? extends Object>> {...} 

, но тогда у меня нет типа псевдонима (U) для метода public T getObjectId(U id). Единственное решение, которое я нашел, чтобы решить это с помощью 2 параметров типа:

public interface IdObjectDAO<T extends IdObject<U>, U> {...} 

, но я хочу, чтобы избежать использования этих 2 параметров типа, чтобы не указывать тип идентификатора в модели и DAO классов:

public class  Person extends IdObject<Integer> {...} 
public interface PersonDAO extends IdObjectDAO<Person, Integer> {...} 
                ^^^^^^^^^ <== avoid this 

Может ли кто-нибудь думать по-другому реализовать этот общий родовой или определить интерфейс IdObjectDAO?

Заранее благодарен!

+1

Я думаю, что версия два параметра является правильным и единственным способом сделать это , Вы ожидаете, что компилятор сможет «заглянуть внутрь» вашего IdObject для типа id, и это просто невозможно. – Chris

+0

Попробуйте это общественный интерфейс IdObjectDAO { public T getObjectById (U id); } –

+0

Это также должно ответить на ваш вопрос: http://stackoverflow.com/questions/14953029/generic-generics-syntax-error-on-token-extends-expected –

ответ

1

Интерфейс определяется не только его именем, но и состоит из подписи всех методов, определенных в нем. Поскольку у вас есть метод

public T getObjectById(U id); 

ваш интерфейс является общим в обоих T и U. Интерфейс не может определить U от IdObject<U>, поэтому вам нужно будет указать его явно, если вы хотите, чтобы скомпилировать тип времени.

Если вы действительно настаиваете на только предоставление T в качестве общего параметра, два (довольно плохо) обходные пути я могу придумать, являются:

1) Lose типобезопасность:

public interface IdObjectDAO<T extends IdObject<?>> { 
    public T getObjectById(Object id); 
} 

Если вы осуществлять equals из U правильно, вы можете успешно назвать

id.equals(t.getId()); 

для объекта t типа T.

2) Оберните свой идентификатор в объекте типа T:

public interface IdObjectDAO<T extends IdObject<?>> { 
    public T getObjectBySample(T sample); 
} 

Вы можете назвать это как:

Integer id = 5; 
Person sample = new Person(id); 
Person object = personDao.getObjectBySample(sample); 
Смежные вопросы