Реализация абстрактного универсального метода в Java с несколькими типами дженериков
Я задам очень короткий вопрос и надеюсь, что кто-то может помочь мне в решении. Он рассказывает о методах дженериков в java с двумя типами дженериков (один для возвращаемого типа и другой для формального пареметра) и о том, как его реализовать. Наверное, я что-то упускаю, чтобы заставить его работать.
дело вот в чем...
это работающего :
public enum Getter
{
BillItemsSize {
@Override
public Integer get (Object entity) {
DesiredClass ref = (DesiredClass ) entity; // "Old time" cast
// do things...
}
};
public abstract <T,K> T get (K entity);
}
это не работает :
public enum Getter
{
BillItemsSize {
@Override
public Integer get (DesiredClass entity) { // no cast at all
// do things
}
};
public abstract <T,K> T get (K entity);
}
в Java компилятор кричит мне :
<anonymous datasource.db.Getter> is not abstract and does not override abstract method <T,K>get(K) in Getter
Ну, это ситуация. Заранее спасибо всем!. Надеюсь, это поможет другим в будущем!.
P. D: это не проблема типов перечислений.. это происходит между иерархиями классов. Так что не стоит винить эмунов... я пробовал это и тоже не работает.
public abstract class SuperClass
{
public abstract <T,E> T pepe (E e);
}
public class SubClass extends SuperClass
{
@Override
public Integer pepe(DesiredClass e) // fails...
{
return null;
}
}
обновление:
для обобщения параметров
мы можем сделать общее правило, что для " дженериков параметр " (те, чьи типы являются универсальными) тип, неявно принятый в сигнатуре метода, равен верхним границам этого универсального, который может быть объектом, если ничего не указано, или более конкретным подклассом, если используются верхние границы (в Примере t расширяет строку).
для дженериков возвращает типы
нет проблем с перезаписью универсального метода с определенным типом возврата, если тип возврата является подтипом перезаписанного типа возврата. И что тип возврата на первом месте? Так случилось, что это объект. По умолчанию компилятор принимает (в сигнатуре метода) универсальный тип в качестве типа объекта.
поэтому мы должны знать, что трюк состоит в том, чтобы знать, что любой метод, имеющий общий тип возврата, на самом деле имеет объект тип возвращаемого значения. Тогда, если в любом подклассе метод перезаписывается и мы изменяем тип возврата, заявляя, что возвращаем другой тип, проблем не будет. Потому что, кроме того, что метод вернет объект другого класса, этот возвращаемый объект неизбежно будет подклассом класса Object, и не будет никаких проблем с перезаписью метода с другим типом возврата, который является исходным, пока он является подтипом оригинала. Метод, называемый ковариантным типом возврата, позволяет нам делать такие вещи.
public abstract class SuperClass
{
public abstract <T> T operation ();
}
public class SubClass extends SuperClass
{
@Override
public Chair operation()
{
//bla bla
}
}
тем временем в другой части кода...
void main ()
{
SubClass sb = new SubClass();
Chair chair = sb.operation ();
// the chair type can be easely replaced by super type (like Object)
Object object = sb.operation();
}
спасибо всем людям, которые помогают убрать это!.
2 ответов
public abstract <T,K> T get (K entity);
- это метод, который может принимать что угодно в качестве аргумента и может возвращать что угодно.
перекрывая его с
public Integer get (DesiredClass entity)
не работает, так как вы ограничиваете типы аргументов, которые могут быть переданы методу в DesiredClass, и, таким образом, нарушаете принцип Лискова.
было бы легче понять без дженериков. Предположим, у вас есть абстрактный метод в классе-бар:
public abstract void fillRecipient(Recipient r);
и вы пытаетесь переопределить в SubBar это с
public void fillRecipient(Glass glass) {
}
что бы сделал следующий код, если бы вышеуказанное было законным?
Bar bar = new SubBar();
bar.fillRecipient(new Mug());
завершить к JB Nizet это ответ, когда вы пишете:
<K>
это неявно означает:
<K extends Object>
этот метод должен принимать какого-либо объекта. Ограничивая его DesiredClass
в подклассе эффективно ничего не перезаписывает, как говорится в сообщении об ошибке.
переопределенные методы должны иметь точно такую же сигнатуру, никакие sub / super типы не разрешены ни в параметрах, ни в возврате типы.
Edit: на самом деле, как обсуждалось в комментариях,String public foo();
эффективно переопределяет Object public foo();
.