Я хотел бы использовать интерфейс в качестве короткого имени для параметризованного интерфейса, чтобы избежать загрязнения всего кода общим синтаксисом. Например:
EggChicken egg = chicken.lay(); // Can't make it compile.
вместо:
Egg<AnimalChicken> egg = chicken.lay(); // Compiles happily.
Скажем, я хотел бы смоделировать режимы размножения животных, используя параметризованные классы (https://en.wikipedia.org/wiki/Modes_of_reproduction). У меня есть следующие интерфейсы:
public interface Animal<T> {
T lay();
}
interface Viviparous<T extends Viviparous> extends Animal<T> {
}
interface Egg<T extends Oviparous> {
T hatch();
}
interface Oviparous<T extends Oviparous> extends Animal<Egg<T>> {
}
Идея состоит в том, что живородящие животные откладывают новые экземпляры того же животного, тогда как яйцекладущие животные откладывают яйца, которые вылупляются новые экземплярыэтого же животного.
Теперь я хотел бы определить более точные интерфейсы для описания собаки и цыпленка:
interface AnimalDog extends Viviparous<AnimalDog> {
}
interface AnimalChicken extends Oviparous<AnimalChicken> {
}
interface EggChicken extends Egg<AnimalChicken> {
}
Наконец, это реализации:
public class AnimalDogImpl implements AnimalDog {
@Override
public AnimalDog lay() {
return new AnimalDogImpl();
}
}
class AnimalChickenImpl implements AnimalChicken {
@Override
public EggChickenImpl lay() {
return new EggChickenImpl();
}
}
public class EggChickenImpl implements EggChicken {
@Override
public AnimalChicken hatch() {
return new AnimalChickenImpl();
}
}
Моя проблема возникает, когда я хочу использовать классы в коде:
public class AnimalTest {
@Test
public void can_do_something_nice() {
AnimalChicken chicken = new AnimalChickenImpl();
// Error here:
EggChicken egg = chicken.lay();
AnimalChicken chick = egg.hatch();
Assertions.assertThat(chick).isNotNull();
}
}
Я получаю ошибку: Обязательный EggChicken, найдено Egg , но этокак именно я определил EggChicken
. Можно ли решить этот тип косвенного обращения?