Почему множественное наследование не разрешено в Java или C #? - PullRequest
103 голосов
/ 15 июня 2009

Я знаю, что множественное наследование не разрешено в Java и C #. Многие книги просто говорят, множественное наследование не допускается. Но это можно реализовать с помощью интерфейсов. Ничего не обсуждается, почему это не разрешено. Кто-нибудь может сказать мне точно, почему это не разрешено?

Ответы [ 17 ]

134 голосов
/ 15 июня 2009

Короткий ответ: потому что разработчики языка решили не делать этого.

По сути, казалось, что и разработчики .NET и Java не допускали множественное наследование, потому что они рассуждали, что добавление MI добавило слишком много сложности к языкам, обеспечивая слишком мало выгоды .

Для более увлекательного и подробного чтения в Интернете доступны некоторые статьи с интервью некоторых дизайнеров языка. Например, для .NET Крис Брамм (который работал в MS над CLR) объяснил причины, по которым они решили не делать:

  1. Различные языки на самом деле имеют разные ожидания относительно того, как MI работает. Например, как конфликты решены ли дублирующие базы объединены или избыточны. Прежде чем мы сможем реализовать MI в CLR, мы должны сделать опрос всех языков, рисунок из общих понятий, и решить как выразить их в не зависящая от языка манера. Мы также должны решить, принадлежит ли МИ в CLS и что это будет означать для языки, которые не хотят этого понятия (предположительно VB.NET, например). из Конечно, это бизнес, в котором мы находимся как общеязыковая среда выполнения, но мы не удосужился сделать это для MI еще.

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

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

Вы можете прочитать статью полностью здесь.

Для Java вы можете прочитать эту статью :

Причины пропуска нескольких наследование от языка Java в основном проистекает из "простой, объект ориентированная и знакомая "цель. Как простой язык, создатели Java хотел язык, который большинство разработчиков мог понять без обширного повышение квалификации. С этой целью они работали для сделать язык похожим на C ++ как можно (знакомо) без ношения над ненужной сложностью C ++ (просто).

По мнению дизайнеров, несколько наследование вызывает больше проблем и путаница, чем она решает. Так они режут множественное наследование от языка (так же, как они режут оператор перегрузки). Дизайнеры обширные Опыт С ++ научил их этому множественное наследование просто не стоило головная боль.

91 голосов
/ 15 июня 2009

Множественное наследование реализации - это то, что не разрешено.

Проблема в том, что компилятор / среда выполнения не могут понять, что делать, если у вас есть класс Cowboy и Artist, оба с реализациями для метода draw (), а затем вы пытаетесь создать новый тип CowboyArtist. Что происходит, когда вы вызываете метод draw ()? Кто-то лежит на улице мертвым или у вас есть прекрасная акварель?

Я считаю, что это называется проблемой двойного бриллианта.

19 голосов
/ 12 декабря 2013

Причина: Java очень популярен и легко кодируется благодаря своей простоте.

Так что то, что когда-либо разработчики java чувствуют, что программистам сложно и сложно понять, они пытались избежать этого. Одним из таких видов имущества является множественное наследование.

  1. Они избегали указателей
  2. Они избежали множественного наследования.

Проблема с множественным наследованием: Проблема с бриллиантом.

Пример :

  1. Предположим, что класс A имеет метод fun (). класс B и класс C происходят от класса A.
  2. И оба класса B и C переопределяют метод fun ().
  3. Теперь предположим, что класс D наследует и класс B, и C. (только предположение)
  4. Создать объект для класса D.
  5. D d = новый D ();
  6. и попробуйте получить доступ к d.fun (); => это будет вызывать fun класса B () или Fun класса C?

Это неопределенность, существующая в проблеме алмазов.

Не является невозможным решить эту проблему, но это создает больше путаницы и сложностей для программиста при его чтении. Это вызывает больше проблем, чем пытается решить.

Примечание : Но в любом случае вы всегда можете косвенно реализовать множественное наследование с помощью интерфейсов.

13 голосов
/ 15 июня 2009

Потому что в Java философия дизайна сильно отличается от C ++. (Я не собираюсь обсуждать C # здесь.)

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

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

Кроме того, Java была в значительной степени реакцией C ++ и Smalltalk, наиболее известных ОО-языков. Существует множество других ОО-языков (Common Lisp был фактически первым стандартизированным языком) с различными ОО-системами, которые лучше справляются с MI.

Не говоря уже о том, что в Java вполне возможно сделать MI, используя интерфейсы, композицию и делегирование. Он более явный, чем в C ++, и, следовательно, более громоздкий в использовании, но даст вам то, что вы, скорее всего, поймете на первый взгляд.

Здесь нет правильного ответа. Существуют разные ответы, и какой из них лучше для данной ситуации, зависит от приложений и индивидуальных предпочтений.

12 голосов
/ 15 июня 2009

Основной (хотя отнюдь не единственной) причиной, по которой люди уклоняются от MI, является так называемая «проблема с бриллиантами», приводящая к неопределенности в вашей реализации. Эта статья в Википедии обсуждает это и объясняет лучше, чем я мог. MI также может привести к более сложному коду, и многие разработчики OO утверждают, что MI вам не нужен, и если вы его используете, ваша модель, вероятно, ошибочна. Я не уверен, что согласен с этим последним пунктом, но придерживаться простых правил - это всегда хороший план.

8 голосов
/ 15 июня 2009

Множественное наследование

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

Таким образом, можно считать разумным выбор, если не включить множественное наследование в язык Java.

8 голосов
/ 15 июня 2009

В C ++ множественное наследование было основной головной болью при неправильном использовании. Чтобы избежать этих популярных проблем проектирования, в современных языках вместо наследования нескольких интерфейсов (java, C #).

.
5 голосов
/ 15 июня 2009

Другая причина состоит в том, что одиночное наследование делает приведение тривиальным, не испуская никаких инструкций ассемблера (кроме проверки совместимости типов, где это требуется). Если бы у вас было множественное наследование, вам нужно было бы выяснить, где в дочернем классе начинается определенный родительский класс. Таким образом, производительность, безусловно, является преимуществом (хотя и не единственным).

4 голосов
/ 12 января 2013

Динамическая загрузка классов затрудняет реализацию множественного наследования.

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

алмазная проблема множественного наследования. У нас есть два класса B и C, наследуемых от A. Предположим, что B и C переопределяют унаследованный метод, и они предоставляют свою собственную реализацию. Теперь D наследует от B и C, делая множественное наследование. D должен наследовать этот переопределенный метод, jvm не может решить, какой переопределенный метод будет использоваться?

В c ++ виртуальные функции используются для обработки, и мы должны делать это явно.

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

4 голосов
/ 15 июня 2009

Я принимаю утверждение, что «множественное наследование не разрешено в Java» с щепоткой соли.

Множественное наследование определяется, когда «Тип» наследуется от более чем одного «Типа». И интерфейсы также классифицируются как типы, поскольку они имеют поведение. Так что Java имеет множественное наследование. Просто это безопаснее.

...