2016-12-21 1 views
3

Проблема:Java-не обеспечивает такое же решение разрешить множественное наследование, которое они дали решить методы интерфейса по умолчанию

Мы знаем, что Java не позволяет несколько классов, так как это привело бы в Diamond Problem где компилятор не может решить, какой метод суперкласса использовать. С помощью методов по умолчанию в интерфейсе Diamond Problem были представлены в Java 8. То есть, если класс реализует два интерфейса, каждый из которых определяет один и тот же метод по умолчанию, а класс реализации не переопределяет общий метод по умолчанию, компилятор не может решить, какую реализацию выбрать.

Решение:

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

Вопрос:

Почему это решение не применимо для наследования множественного класса, путем переопределения общих методов, введенных класса ребенка?

ответ

0

Методы, представленные интерфейсами, всегда могут быть переопределены, а методы, введенные классами, могут быть окончательными. Это одна из причин, по которой вы потенциально не могли применить ту же стратегию для классов, что и для интерфейсов.

5

Правильно вы не поняли проблему с алмазом (и предоставлено, текущее состояние статьи в Википедии не объясняет это достаточно). Как показано на этом графике,

A true diamond

проблема алмаза происходит, когда тот же класс наследуется несколько раз по различным путям наследования. Это не проблема для интерфейсов (и никогда не было), поскольку они определяют контракт и определяют один и тот же контракт несколько раз.

Основная проблема не связана с методами, но данные этого супер-типа. Если состояние экземпляра A существует один или два раза в этом случае? Если один раз, C и B могут иметь разные конфликтующие ограничения на состояние экземпляра A. Оба класса могут также предполагать полный контроль над состоянием A, т. Е. Не считать, что другой класс имеет тот же уровень доступа. Если имеется два разных состояния A, то более широкое преобразование ссылки на ссылку A становится двусмысленным, так как может быть обозначен либо A.

Интерфейсы не имеют этих проблем, так как они не содержат данных экземпляра. У них также (почти) нет проблем с доступностью, так как их методы всегда public. Разрешающие методы default не изменяют это, поскольку методы default по-прежнему не имеют доступа к переменным экземпляра, но работают только с интерфейсами.

Конечно, есть вероятность того, что B и C объявили default методы с одинаковой сигнатурой, что приводит к неоднозначности, которая должна быть решена в D. Но это даже так, когда нет A, то есть нет «алмаза» вообще. Таким образом, этот сценарий не является правильным примером «проблемы с алмазами».

+0

Я согласен с аргументом общего состояния для проблемы с алмазом, но не менее, если бы у вас была поддержка множественного наследования в * Java *, вам пришлось бы решить проблему выбора одной из нескольких реализаций одного метод. Эта проблема заявлена ​​в вопросе и как она решена для интерфейсов в Java 8. То же самое решение не может быть применено для классов. Или я что-то пропустил? – Harmlezz

+2

@ Harmlezz: как указано в последнем абзаце, проблема, связанная с необходимостью устранения неоднозначности между несколькими унаследованными неавтоматическими методами, является проблемой множественного наследования в целом, но для этого не требуется общий тип супер, поэтому , не имеет отношения к проблеме * Diamond *. Вы правы, что это проблема, которая не может быть решена вообще для классов, отличных от '' interface', но тем не менее, это не особая проблема, называемая «Проблема с алмазами». – Holger

0

конфликт описывается как «проблема алмазов» лучше всего можно проиллюстрировать с помощью полиморфного вызов метода A.m(), где тип приёмника времени выполнения имеет тип D: Imagine D наследует два различных метода как утверждающего играть роль A.m() (один из них может быть исходный метод A.m(), по крайней мере один из них является переопределением). Теперь динамическая отправка не может решить, какой из конфликтующих методов вызывать.

Помимо: различия betwee «проблем алмазов» и регулярные столкновения имен особенно актуально в таких языках, как Eiffel, где конфликт может быть локально решено на перспективу типа D, например, путем переименования одного метода. Это позволило бы избежать столкновения имени для вызовов со статическим типом D, но не для вызовов со статическим типом A.

Теперь, с использованием методов по умолчанию в Java 8, в JLS были внесены поправки с правилами, которые обнаруживают любые такие конфликты, требуя для разрешения конфликта D (существует много различных случаев, в зависимости от того, являются ли некоторые из типов, которые являются классами) , I.e, проблема алмаза не «решена» в Java 8, ее просто избегают, отвергая любые программы, которые ее создавали.

В теории аналогичные правила могут определены на Java 1, чтобы допускать множественное наследование для классов. Это просто решение, которое было принято на раннем этапе, что разработчики Java не хотят для поддержки множественного наследования.

Выбор допускать множественное (внедрение) наследования для методов по умолчанию, но не для методов класса, является чисто прагматичным выбором, не требующим какой-либо теории.

Смежные вопросы