Если вас беспокоит удаление, просто используйте отдельные имена методов для отдельных методов:
abstract class TopLevelClass {
void fooTop(Strategy<TopLevelClass> s) {/*...*/}
}
class MidLevelClass extends TopLevelClass {
void fooMid(Strategy<MidLevelClass> s) {/*...*/}
}
class LowLevelClass extends MidLevelClass {
void fooLow(Strategy<LowLevelClass> s) {/*...*/}
}
Однако, я подозреваю, удаление - не ваша проблема . Вероятно, вы хотите переопределить тот же метод.
Экземпляр Strategy<LowLevelClass>
не может быть Strategy<MidLevelClass>
, который не может быть стратегией;
Учитывая
Strategy<LowLevelClass> l;
Strategy<MidLevelClass> m;
Тогда вы не можете назначить одно другому.
l = m; // Compile-time fail.
m = l; // Compile-time fail.
И поэтому не имеет смысла делать то же самое с помощью переопределения метода. (Также всегда было верно, что bar(TopLevelClass)
не может переопределить bar(MidLevelClass)
, хотя начиная с 1.5 существуют ковариантные возвращаемые типы.)
Добавьте параметр типа в класс для использования в качестве аргумента типа в методе.
abstract class TopLevelClass<T extends TopLevelClass<T>> {
void foo(Strategy<T> s) {/*...*/}
}
class MidLevelClass<T extends MidLevelClass<T>> extends TopLevelClass<T> {
void foo(Strategy<T> s) {/*...*/}
}
class LowLevelClass<T extends LowLevelClass<T>> extends MidLevelClass<T> {
void foo(Strategy<T> s) {/*...*/}
}
В обновленном вопросе добавлено использование this
в качестве аргумента для вызова Strategy.foo
. Это означает, что MidLevelClass
должно быть abstract
- это не может гарантировать, что foo
переопределено. Тип this
теперь должен соответствовать параметру типа. Для этого добавьте метод abstract
"getThis" (бетон в конкретных подклассах).
protected abstract X getThis();
...
@Override protected X getThis() { return this; }
Тип полей static
требует подстановочных знаков:
static final Strategy<? extends TopLevelClass<?>> s1 =
tlc -> System.out.println(tlc.getTopLevelAtt());
(лучшие дизайны предпочитают композицию наследованию.)