почему vb.net не поддерживает множественное наследование?

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

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


person yamspog    schedule 03.05.2010    source источник
comment
Вы, вероятно, слышали, как это обсуждалось в отношении C#, потому что C# ближе к C++, где поддерживается MI. С другой стороны, основной целью VB как языка программирования была простота, а не сложность, поэтому большинство программистов не ожидали, что VB будет поддерживать MI.   -  person Jim Anderson    schedule 28.05.2010


Ответы (6)


Он не реализован в CLR, поэтому недоступен в CLS-совместимых языках, таких как VB.NET. Кажется, среди инженеров Microsoft, в том числе Андерса Хейлсберга, ведущего архитектора C#, существует общее мнение, что потенциальные преимущества не стоят затрат и сложности реализации. Крис Брамм, выдающийся инженер в команде .NET в то время, сказал это еще в 2004 году:

Есть несколько причин, по которым мы не предоставили готовую, проверяемую, CLS-совместимую версию множественного наследования реализации:

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

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

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

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

[Ссылка]

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

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

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

person Tom Cabanski    schedule 03.05.2010

Все языки dotNET используют общую систему типов, и эта CTS не поддерживает множественное наследование. Конкретный язык, такой как VB или C#, не может добавить это сам по себе, он станет несовместимым с остальной частью dotNET. В лучшем случае язык может выбрать игнорирование/скрытие такой функции.

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

person Henk Holterman    schedule 03.05.2010
comment
И обычно в C ++ предпочтительно, чтобы множественное наследование использовалось только для поддержки шаблона одного базового класса + нескольких интерфейсов и ветвления только в том случае, если вам действительно-действительно-действительно нужен класс из двух базовых классов. - person SztupY; 04.05.2010

Отсутствие MI (множественное наследование) сильно связано как с дизайном языка, так и с предполагаемым хостом (CLR):

1) Разница в MI/SI настолько фундаментальна для языка, что очень сложно (или, возможно, невозможно) «добавить ее как функцию» позже.

2) Что касается предполагаемого хоста: хотя было бы возможно написать язык MI для CLR (так же, как было бы возможно написать язык с продолжениями и т. д. для CLR - это можно сделать) заключается в том, что при этом вы теряете совместимость со всеми другими языками ".NET".

Гораздо более простая форма «MI», которую можно модифицировать в CLR, — это Traits, обрабатываемые посредством свертывания MRO во время компиляции (вот как Scala поддерживает Traits на JVM). Тем не менее, это по-прежнему требует значительного редизайна/переосмысления языка, а для чего-то вроде "проверенного" как VB(.NET) удачи :-) Нужно убедиться, что он хорошо сочетается с существующим кодом. имеет большое значение при добавлении улучшений в язык.

person Community    schedule 03.05.2010

Есть много других техник, которые значительно превосходят МИ, например, композиция. Даже в таких языках, как C++, поддерживающих MI, невероятно редко можно увидеть, как класс умножается на наследство от двух неабстрактных базовых классов.

person Puppy    schedule 03.05.2010

Почему C# или VB.NET не поддерживают множественное наследование

http://royalarun.blogspot.in/2013/05/why-c-or-vbnet-doesnt-support-multiple.html

1) Первая причина - двусмысленность вокруг проблемы Diamond, рассмотрим, что класс A имеет метод foo(), а затем B и C производные от A и имеют собственную реализацию foo(), и теперь класс D происходит от B и C с использованием множественного наследования, и если мы ссылайтесь только на foo(), компилятор не сможет решить, какой foo() он должен вызывать. Это также называется проблемой ромба, потому что структура этого сценария наследования аналогична ромбу с 4 ребрами, см. Ниже.

      A foo()
       / \
      /   \  
foo() B     C foo()  
      \   /  
       \ /  
        D
       foo()

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

Иногда, если вы объясните эту причину интервьюеру, он спросит, может ли C ++ поддерживать множественное наследование, а почему бы и нет c # oR vb.net. В этом случае я попытаюсь объяснить ему вторую причину, которую я привел ниже, что это не из-за технических трудностей. но движущим фактором был более удобный и понятный дизайн, хотя это может подтвердить только любой дизайнер Java, и мы можем только строить догадки. В ссылке на Википедию есть хорошее объяснение того, как возникает проблема с адресом на другом языке из-за проблемы с бриллиантом при использовании множественного наследования.

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

person Arun Prakash    schedule 08.11.2013

Предположим, тип B имеет виртуальный метод m, который типы X и Y реализуют по-разному, хотя обе реализации связаны с base.m(), D происходит от X и Y без определения собственной реализации, а George является экземпляром D. Класс X будет ожидать, что ни один производный класс не получит доступ к B.m() без собственной реализации этого метода, и класс Y будет иметь аналогичное ожидание. Нет ничего, что компилятор мог бы CType(George,B).m() сделать, что не нарушило бы таких ожиданий. Если бы для прохождения через тип X или Y требовалось восходящее преобразование из типа D в B, то приведение, прошедшее через X, могло бы использовать метод X, а приведение, прошедшее через Y, могло бы использовать метод Y, но тогда ссылка на D не была бы прямой. может использоваться кодом, который ожидает ссылку на B (или, если уж на то пошло, Object). Требование, чтобы только интерфейсы могли быть множественно унаследованы, и чтобы каждый тип, реализующий интерфейс, предоставлял реализации всех методов, почти так же хорош, как и предоставление обобщенного множественного наследования, но не вызывает такой же неоднозначности.

person supercat    schedule 09.11.2013