Java поддерживает ковариантные типы возврата, так что это один из вариантов.Воспользуйтесь тем фактом, что A
и B
являются производными от Object
:
public interface I {
Object getSelf(); // or I, see below
}
public class A implements I {
A getSelf() { return this; }
}
public class B implements I {
B getSelf() { return this; }
}
Суть в том, что оба значения A.getSelf()
и B.getSelf()
являются законными переопределениями I.getSelf()
,хотя их тип возврата отличается.Это потому, что каждый A
может обрабатываться как и Object
, и поэтому тип возвращаемого значения совместим с типом возвращаемого значения базовой функции.(Это называется «ковариация».)
На самом деле, поскольку известно, что A
и B
также получены из I
, вы можете заменить Object
на I
по тем же причинам..
Ковариация, как правило, хорошая вещь: кто-то, у кого есть интерфейсный объект типа I
, может вызвать getSelf()
и получить другой интерфейс, и это все, что ей нужно знать.С другой стороны, тот, кто уже знает, что у него есть объект A
, может вызвать getSelf()
и фактически получит еще один объект A
.Дополнительную информацию можно использовать для получения более конкретного производного типа, но тот, кому не хватает этой информации, получает все, что предписано базовым классом интерфейса:
I x = new A();
A y = new A();
I a = x.foo(); // generic
A b = y.foo(); // we have more information, but b also "is-an" I
A c = (A)x.foo(); // "cheating" (we know the actual type)