Подтвердить что ты не робот

Как применить больше ограничений для объявления интерфейса в Java?

Скажем, у меня есть интерфейс:

interface Mammal {
    void marry(Mammal m);
    Mammal giveBirthTo();
}

Однако это не совсем то, что я хочу.

Очевидно, что человек не может жениться на собаке и не родить кошку. Итак, как я могу вставлять эту информацию в интерфейс, так что тип ввода и тип вывода могут быть автоматически изменены по мере их внедрения?

4b9b3361

Ответ 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
}