Подтвердить что ты не робот

Как С# отсутствие множественного наследования привело к необходимости использования интерфейсов?

В Язык программирования С# Krzysztof Cwalina заявляет в аннотации:

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

Интерфейсы являются основной концепцией для языков программирования OO. Я не придерживаюсь значения "заставил нас добавить концепцию интерфейсов"

Знает ли Кшиштоф, что необходимо принять определенные проектные решения в отношении использования интерфейсов, в которых в противном случае использовалось бы многоуровневое наследование? Или он имеет в виду, что interface были введены в С# из-за отсутствия множественного наследования? Можете ли вы привести пример?

4b9b3361

Ответ 1

Интерфейс - это просто базовый класс, который не имеет элементов данных и определяет только методы public abstract. Например, это будет интерфейс в С++:

class IFrobbable {
    public:
    virtual void Frob() = 0;
}

Поэтому, когда MI доступен как функция языка, вы можете "реализовывать" интерфейсы, просто вызывая их (опять же, С++):

class Widget : public IFrobbable, public IBrappable {
    // ...
}

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

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

Итак, я интерпретирую цитату Кшиштофа как

Множественное наследование в общем случае - очень сложная проблема, которая мы не могли справиться удовлетворительно, учитывая реальную жизнь ограничения на развитие .NET. Однако наследование интерфейсов так много проще решать и высшую важность в ООП, поэтому мы сделали это но, конечно, интерфейсы также имеют свой собственный набор проблем, в основном относительно того, как структурируется BCL.

Ответ 2

Из Chris Brumme:

Существует несколько причин, по которым мы не реализуем Multiple Наследование непосредственно. (Как вы знаете, мы поддерживаем Multiple Наследование интерфейса).

Я думаю, что Krzysztof Cwalina заявляет в цитате не понятие самих интерфейсов, а многократное наследование интерфейса как метод множественного наследования.

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

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

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

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

Ответ 3

Я думаю, вы должны прочитать, что говорит Эрик Липперт о Interfaces. У него грязные руки, поэтому я думаю, что он знает лучше всех.

Иногда бывают худшие случаи и худшие случаи. Вы должны выбрать менее плохую.

Ниже приведена копия связанного сообщения:


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

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

Тем не менее, интерфейсы являются довольно слабым способом представления контрактных обязательств. Если вам нужен более сильный и гибкий способ представления контрактных обязательств, посмотрите на функцию "Кодовые контракты", которая поставляется с последней версией Visual Studio.

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

Хорошо, я рад, что вам это нравится.

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

Ответ 4

Я думаю, что язык Cwalina немного силен и не совсем точно относится к истории.

Помните, что интерфейсы были до С#, поэтому сказать, что "мы должны были добавить интерфейсы для решения проблемы x", это звучит не так. Я думаю, что интерфейсы были бы там по умолчанию - они должны были быть.

Кроме того, помните, что С# получен в основном из С++. Или, по крайней мере, люди, участвующие в создании языка С#, имели бы очень сильный фон в С++. Множественное наследование было признанной зоной кошмара на С++. Наследование из нескольких классов, которые сами могут быть получены из базовых классов commonm, разработка которых будет иметь приоритет и т.д. Я имею в виду, что это очень мощная функция, но, без сомнения, может привести к сложному коду.

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

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