Множественная критика наследования - PullRequest
2 голосов
/ 10 февраля 2009

Я исследовал концепцию множественного наследования (прошло почти 10 лет с тех пор, как я закодировал C ++ в гневе и просто академически интересовался этой концепцией). Я нашел эту ссылку в Википедии.

Одна критика MI, которую они перечисляют, заключается в «невозможности явного наследования несколько раз от одного класса». Я запутался в этом утверждении и не уверен на 100%, к чему это относится.

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

Я хотел бы понять, на что ссылается эта критика и почему она неявно недоступна для языков с множественным наследованием.

Ответы [ 6 ]

6 голосов
/ 10 февраля 2009

Это называется Алмазная проблема . Большинство современных языков, которые позволяют MI, имеют решение для этого.

Короче говоря, у вас есть это дерево классов:

class A { public int f = 0; };

class B extends A { f = 1; };

class C extends A { f = 2; };

class D extends B, C {};

Что будет печатать D.f? Если вы поместите какое-то значение в D.f, где оно должно храниться? Должны ли два поля B (A) .f и C (A) .f быть объединены в одно или они должны оставаться раздельными? Если вы переопределите метод x из A в B и в C, что должен делать D.x ()? Позвонить обоим? В каком порядке? Как насчет возвращаемого значения?

1 голос
/ 10 февраля 2009

Multiple Inheritance - это GOTO объектно-ориентированного программирования. Он возник из-за подходов, принятых ранними языками ООП (C ++ и т. Д.). Это хорошо работает в правой руке, но это сбивает с толку большую часть других времен.

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

Реализация интерфейсов, за которой следует явное агрегирование, является более понятным, более обслуживаемым способом выполнения тех же действий, что и множественное наследование. Почти все ООП имеют какой-то метод определения интерфейса, почти все ООП могут объединять объекты вместе. Однако ООП решает проблемы, возникающие из-за множественного наследования (проблема с бриллиантами и т. Д.) Различными способами. Как и в случае GOTO, когда вы просматриваете код, используя множественное наследование, неясно, что происходит. Однако, как и GOTO, это может быть полезно в разных обстоятельствах.

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

1 голос
/ 10 февраля 2009

Я думаю, что проблема именно в этой статье в Википедии. Он содержит более одного неуклюжего или расплывчатого утверждения, такого как эти драгоценности:

Tcl допускает наличие нескольких родительских классов - их серийный номер влияет на разрешение имен для членов класса.

и

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

Честно говоря, я не знаю, что автор имел в виду под предложением в вашем вопросе. Это просто еще один пример неопределенности в плохо написанной статье, ИМХО.

1 голос
/ 10 февраля 2009

Я думаю, что они имеют в виду, что Автомобиль класса не может наследовать от своих четырех колес (например, наследовать четыре раза от Колеса класса). [Смотрите раздел C ++ на той же странице Википедии]

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

1 голос
/ 10 февраля 2009

Точно так же я не кодировал C ++ в гневе более 5 лет, перешел на C #. Я не могу вспомнить, много ли я использовал множественное наследование, но я не скучаю по нему, особенно потому, что могу кодировать интерфейсы и что я больше использую композицию в наши дни.

Однако, в лучшая ОО книга когда-либо - вероятно;) - Бетранд Мейер хорошо защищает множественное наследование. Он также делает подобную защиту здесь .

0 голосов
/ 10 февраля 2009

На самом деле, в C ++ класс может наследовать несколько раз от одного и того же класса:

класс A {};

класс B: общедоступный A ();

класс C: общедоступный A ();

класс D: общедоступный B, общедоступный C {};

Теперь D заканчивается двумя копиями A. Обычно это считается «плохой идеей», и C ++ предоставляет виртуальное наследование для управления им.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...