Множественная неоднозначность наследования с интерфейсом
Мы все знаем о проблеме алмаза относительно множественного наследования -
A
/ \
B C
\ /
D
Эта проблема описывает неоднозначную ситуацию для класса D
. Если класс A
имеет метод, и оба/из B
и/или C
переопределяют метод, а какая версия метода D
переопределяет?
Является ли эта проблема применимой и для интерфейсов в Java? Если нет, как интерфейсы Java справляются с этой проблемой?
Ответы
Ответ 1
Проблема с алмазом применяется только к наследованию реализации (extends
во всех версиях Java до Java 8). Это не относится к наследованию API (implements
во всех версиях Java до Java 8).
Поскольку методы интерфейса с сигнатурами типа соответствия совместимы, проблема с алмазом отсутствует, если вы дважды наследуете одну и ту же подпись метода: вместо этого подписи сигнатур метода просто сливаются. (И если подписи типов не совпадают, то у вас также нет проблемы с алмазом.)
В Java 7 и ниже единственным способом наследования кода реализации было использование ключевого слова extends
, которое ограничивает не более одного родителя. Поэтому нет наследования множественных реализаций и проблемы с алмазом не существует.
Java 8 добавляет новую морщину, потому что она позволяет интерфейсам иметь код реализации. Он все еще избегает проблемы с алмазом, просто отступая от предыдущего поведения (без наследования реализации), когда вы реализуете несколько интерфейсов с методами, имеющими соответствующие подписи.
Ответ 2
Java преодолевает эту проблему, даже если интерфейсы могут иметь стандартные реализации методов, поскольку реализация по умолчанию либо однозначна (одна в классе A
), либо ситуация решается некоторым правилом (когда класс B
или класс C
переопределяет реализацию из класса A
, см. ниже).
Когда супертипы класса или интерфейса предоставляют несколько методов по умолчанию с одинаковой сигнатурой:
- Методы экземпляров предпочтительнее, чем методы интерфейса по умолчанию.
- Методы, которые уже переопределены другими кандидатами, игнорируются. Это обстоятельство может возникнуть, когда супертипы имеют общий предок.
Однако, если конфликтуют два или более независимых метода по умолчанию, или метод по умолчанию конфликтует с абстрактным методом, тогда компилятор Java создает ошибку компилятора. Вы должны явно переопределить методы супертипа. В этом случае вы можете вызывать любую из реализаций по умолчанию с ключевым словом super.
См. также: Как работает новая модель интерфейса Java 8 (включая алмаз, множественное наследование и приоритет)?
Ответ 3
Java не поддерживает множественное наследование, поэтому проблема с алмазом не возникает. Если B и C являются интерфейсами, то в интерфейсах нет реализации. Даже если B и C переопределяют метод в интерфейсе A (не может быть классом), методы будут иметь одну и ту же подпись. Нет никакой двусмысленности в отношении того, какую реализацию использовать, потому что нет реализации.
Ответ 4
При использовании стандартных методов в интерфейсе, введенных в Java 8, может возникнуть проблема с несколькими наследованиями, существует 3 сценария -
1- Если реализация класса переопределяет метод по умолчанию и предоставляет свои собственные функции для метода по умолчанию, то метод класса имеет приоритет над методами интерфейса по умолчанию.
2. Когда класс реализует оба интерфейса и оба имеют один и тот же метод по умолчанию, также класс не переопределяет этот метод, тогда будет вызвана ошибка.
3 - В случае, когда интерфейс расширяет другой интерфейс, и оба имеют один и тот же метод по умолчанию, метод по умолчанию наследующего интерфейса будет иметь приоритет.
Подробнее об этом здесь.
Ответ 5
Чтобы добавить к существующим ответам о множественном наследовании Java8 с интерфейсами (a.k.a., как Java по-прежнему избегает проблемы с алмазами):
Существует три правила:
![введите описание изображения здесь]()
- Если выше не так, наследующий класс должен явно указывать используемую им реализацию метода (иначе он не будет компилироваться)
![введите описание изображения здесь]()