Как применить больше ограничений для объявления интерфейса в Java?
Скажем, у меня есть интерфейс:
interface Mammal {
void marry(Mammal m);
Mammal giveBirthTo();
}
Однако это не совсем то, что я хочу.
Очевидно, что человек не может жениться на собаке и не родить кошку. Итак, как я могу вставлять эту информацию в интерфейс, так что тип ввода и тип вывода могут быть автоматически изменены по мере их внедрения?
Ответы
Ответ 1
Вы можете использовать дженерики и изменить свой дизайн.
Что-то в строках:
interface Marriable<T extends Mammal> {
void marry(T sweetHalf);
T giveBirthTo();
}
... где Mammal
- ваш верхний интерфейс или абстрактный класс, а Human
, Dog
, Unicorn
и т.д. расширяют/реализуют его.
Ответ 2
Вы можете создать свой интерфейс с помощью переменной рекурсивного типа:
interface Mammal<T extends Mammal<T>> {
void marry(T m);
T giveBirthTo();
}
Таким образом, компилятор Java может дать вам определенный уровень проверки. Обратите внимание, однако, что этот подход по-прежнему открыт для злоупотреблений. Например:
class Cat implements Mammal<Cat> {
@Override void marry(Cat cat) { ... }
@Override Cat giveBirthTo() { ... }
}
class Dog implements Mammal<Cat> { // implements wrong interface
@Override void marry(Cat cat) { ... }
@Override Cat giveBirthTo() { ... }
}
Компилятор может только гарантировать, что вы реализуете интерфейс Mammal
некоторым подтипом одного и того же интерфейса, но не конкретным классом, который его реализует. Это ограничение последнего типа не может быть выражено на языке программирования Java.
Ответ 3
Дженерики. Попробуйте
private static interface Race {
}
private static class Human implements Race {}
private static class Canine implements Race {}
private static interface Being<R extends Race> {
void marry(Being<R> other);
Being<R> giveBirthTo();
}
private void tryMe() {
Being<Human> aHuman = new Being<Human>() {
@Override
public void marry(Being<Human> other) {
}
@Override
public Being<Human> giveBirthTo() {
return null;
}
};
Being<Canine> aCanine = new Being<Canine>() {
@Override
public void marry(Being<Canine> other) {
}
@Override
public Being<Canine> giveBirthTo() {
return null;
}
};
aHuman.marry(aCanine); // not possible
}