Являются ли интерфейсы избыточными с множественным наследованием?

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

Я знаю, что интерфейсы необходимы для тех языков ООП, которые не поддерживают множественное наследование - например, С# и Java. Но как насчет тех, кто имеет множественное наследование? Будет ли концепция интерфейса (как специфической языковой функции) избыточной на языке с множественным наследованием? Я думаю, что ООП "контракт" между классами может быть установлен с использованием абстрактных классов.

Или, если это более явно, являются ли интерфейсы на С# и Java просто следствием того, что они не поддерживают множественное наследование?

Ответ 1

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

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

Тем не менее, я очень доволен одиночным наследованием большую часть времени. Эрик Липперт делает то же самое в том же томе (стр. 10), что выбор одиночного наследования "... устраняет одним ударом многие сложные угловые случаи..."

Ответ 2

Совсем нет. Интерфейсы определяют контракты без указания реализаций.

Поэтому они нужны, даже если присутствует множественное наследование - наследование - это реализация.

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

Ответ 3

Зависит от теста на избыточность.

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

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

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

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

Ответ 4

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

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

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

Таким образом, технические интерфейсы избыточны на языке, который поддерживает MI.

Но, как указывали другие, многократное наследование может быть очень сложной задачей использовать правильно, все время. Я знаю, что не мог... и я работал в Meyer, когда он разрабатывал Object Oriented Software Construction, второе издание.

Ответ 5

Являются ли интерфейсы на С# и Java просто следствием того, что они делают не поддерживают множественное наследование?

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

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

Ответ 6

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

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

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

#if defined(__cplusplus) && !defined(CINTERFACE)
    MIDL_INTERFACE("ABCDE000-0000-0000-0000-000000000000")
    IMyInterface : public IUnknown
    {
   ...
    }
#else   /* C style interface */
    typedef struct IMyInterfaceVtbl
    {
        BEGIN_INTERFACE

        HRESULT ( STDMETHODCALLTYPE *SomMethod )(... ...);

        END_INTERFACE
    } IMyInterfaceVtbl;

    interface IMyInterface
    {
        CONST_VTBL struct IMyInterfaceVtbl *lpVtbl;
    };
#endif

Какой-то другой синтаксический сахар...

И это правда сказать, что в С#, если бы у меня не было понятия интерфейса, я не знаю, как я мог действительно кодировать:). В С# нам абсолютно нужны интерфейсы.

Ответ 7

Интерфейсы предпочтительнее множественного наследования, поскольку наследование нарушает инкапсуляцию в соответствии с "Эффективной Java", пункт 16, Favor composition over inheritance.