Java generics - переопределение абстрактного метода и возвращающий тип подкласса
Я пытаюсь создать набор, в котором набор подклассов переопределяет суперкласс. Этот суперкласс содержит абстрактный метод - тип возврата которого в идеале был бы тем объектом, из которого был вызван этот метод, так что он эффективно ведет себя следующим образом:
public abstract class SuperClass{
public abstract SuperClass getSelf();
}
public class SubClass extends SuperClass{
@Override
public SubClass getSelf(){
return this;
}
}
Я не уверен, что такое возможно, так как я думаю, что возвращаемые типы всегда должны быть одинаковыми для того, чтобы переопределение работало, - но я думал, что ответ, если он существует, лежит где-то вдоль этой линии...
public abstract class SuperClass{
public abstract <? extends SuperClass> getSelf();
}
public class SubClass extends SuperClass{
@Override
public SubClass getSelf(){
return this;
}
}
Спасибо за любую помощь.
edit: добавлено расширение SuperClass в SubClass, duh
Ответы
Ответ 1
Это будет работать:
public abstract class SuperClass{
public abstract SuperClass getSelf();
}
public class SubClass extends SuperClass{
@Override
public SubClass getSelf(){
return this;
}
}
Примечание. Я добавил extends SuperClass
в ваше определение SubClass
. Возвращаемый тип getSelf
называется ковариантным типом возврата.
Ответ 2
Как насчет этого:
public abstract class SuperClass<T extends SuperClass<?>> {
public abstract T getSelf();
}
public class SubClass extends SuperClass<SubClass> {
public SubClass getSelf() {
return this;
}
}
Я знаю, что он довольно повторяющийся и ничто не ограничивает тип как тот же экземпляр SubClass
, потому что также AnotherSubClass
удовлетворяет оценке, но по крайней мере он должен делать трюк.
Ответ 3
Вот как это сделать (поскольку JDK 1.5 есть эта вещь, называемая ковариантными типами возврата, где возможно что-то подобное).
abstract class SuperClass<T extends SuperClass<T>>{
public abstract T getSelf();
}
class SubClass extends SuperClass<SubClass> {
public SubClass getSelf() { return this; }
}
public class Generics {
public static void main(String[] args) {
System.out.println(new SubClass().getSelf());
}
}
Обратите внимание на подобное общее определение класса с Enum (http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Enum.html)
Посмотрите, что происходит за кулисами (используя javap SuperClass SubClass):
class SubClass extends SuperClass{
SubClass();
public SubClass getSelf();
public SuperClass getSelf();
}
abstract class SuperClass extends java.lang.Object{
SuperClass();
public abstract SuperClass getSelf();
}
Обратите внимание, как метод подкласса имеет другой тип возвращаемого значения, который является подтипом возвращаемого типа супер метода.
Btw, обратите внимание, что public SuperClass getSelf();
в классе SubClass
фактически является синтетическим методом.