Какова точная проблема со множественным наследованием?

115
задан casperOne 30 August 2012 в 16:24
поделиться

9 ответов

Самая очевидная проблема с функциональным переопределением.

Скажем, имеют два класса A и B, оба из которых определяют метод doSomething. Теперь Вы определяете третий класс C, который наследовался и от A и от B, но Вы не переопределяете doSomething метод.

, Когда семя компилятора этот код...

C c = new C();
c.doSomething();

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

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

Языки как C++ и Java и C# создают фиксированное основанное на адресе расположение для каждого типа объекта. Что-то вроде этого:

class A:
    at offset 0 ... "abc" ... 4 byte int field
    at offset 4 ... "xyz" ... 8 byte double field
    at offset 12 ... "speak" ... 4 byte function pointer

class B:
    at offset 0 ... "foo" ... 2 byte short field
    at offset 2 ... 2 bytes of alignment padding
    at offset 4 ... "bar" ... 4 byte array pointer
    at offset 8 ... "baz" ... 4 byte function pointer

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

Множественное наследование делает его очень хитрым.

, Если класс C наследовался и от [1 110] и от B, компилятор должен решить ли к расположению данные в [1 112] порядок или в [1 113] порядок.

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

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

Так... длинная история, короткая..., это невыносимо для авторов компилятора для поддержки множественного наследования. Таким образом, когда кто-то как Guido van Rossum разрабатывает Python, или когда Anders Hejlsberg разрабатывает c#, они знают, что поддержка множественного наследования собирается сделать реализации компилятора значительно более сложными, и по-видимому они не думают, что преимущество стоит стоимости.

81
ответ дан Tarick Welling 24 November 2019 в 02:26
поделиться

Проблемы Вы, которых упоминают парни, не являетесь действительно этим трудно для решения. На самом деле, например, Eiffel делает это отлично! (и не представляя произвольный выбор или безотносительно)

, Например, если Вы наследовались A и B, оба нечто метода наличия (), тогда конечно, Вы не хотите произвольный выбор в своем классе C, наследовавшемся и A и B. Необходимо или переопределить нечто, таким образом, ясно, что будет использоваться, если c.foo () назовут, или иначе необходимо переименовать один из методов в C. (это могло стать панелью ())

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

45
ответ дан 24 November 2019 в 02:26
поделиться

ромбовидная проблема :

неоднозначность, которая возникает, когда два класса B и C наследовались A, и класс D наследовалась и B и C. Если существует метод в, что B и C имеют переопределенный , и D не переопределяет его, то, какая версия метода делает D, наследуйтесь: это B или тот из C?

... Это называют "ромбовидной проблемой" из-за формы схемы наследования классов в этой ситуации. В этом случае класс A наверху, и B и C отдельно под ним, и D присоединяется к двум вместе в нижней части для формирования ромбовидной формы...

26
ответ дан gnat 24 November 2019 в 02:26
поделиться

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

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

21
ответ дан KeithB 24 November 2019 в 02:26
поделиться

скажем, у Вас есть объекты A и B, которые оба наследованы C. A и B оба нечто реализации () и C не делает. Я называю C.foo (). Какая реализация выбрана? Существуют другие проблемы, но этот тип вещи является большим.

16
ответ дан tloach 24 November 2019 в 02:26
поделиться

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

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

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

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

существуют другие методы как mixins, которые решают те же проблемы и не имеют проблем, которые имеет множественное наследование.

5
ответ дан Mendelt 24 November 2019 в 02:26
поделиться

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

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

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

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

2
ответ дан 24 November 2019 в 02:26
поделиться

Common Lisp Object System (CLOS) - еще один пример чего-то, что поддерживает MI, избегая при этом проблем в стиле C ++: наследованию дается разумный default , при этом позволяя вам явно решать, как, скажем, вызывать поведение суперпользователя.

3
ответ дан 24 November 2019 в 02:26
поделиться

Я не думаю, что проблема с алмазом - это проблема, я бы считал эту софизму, и ничего больше.

Наихудшая проблема, с моей точки зрения, с множественным наследованием - это RAD - жертвы и люди, которые утверждают, что они разработчики, но на самом деле застряли на полузнании (в лучшем случае).

Лично я был бы очень рад, если бы наконец смог сделать что-то подобное в Windows Forms (это неправильный код, но он должен дать вам идею):

public sealed class CustomerEditView : Form, MVCView<Customer>

Это основная проблема, с которой я столкнулся с отсутствием множественных наследование. Вы МОЖЕТЕ сделать что-то подобное с интерфейсами, но есть то, что я называю «дерьмовым кодом», это этот болезненный повторяющийся треп, который вы должны написать в каждом из ваших классов, например, для получения контекста данных.

На мой взгляд, не должно быть абсолютно никакой необходимости, ни в малейшей степени, в ЛЮБОМ повторении кода на современном языке.

5
ответ дан 24 November 2019 в 02:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: