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

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

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

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


person Mladen Jablanović    schedule 02.12.2010    source источник
comment
Не уверен, что вы здесь ловите: как говорит Божо, интерфейсы - это защита на уровне языка от того, кто-то неожиданно изменит поведение класса, предоставляя реализацию для методов, которые раньше были абстрактными.   -  person Jeff Sternal    schedule 10.12.2010
comment
Вопрос в том, действительно ли языки MI нуждаются в таком хеджировании (например, см. Комментарии Кена ниже). Я также надеялся получить другое мнение за пределами лагерей Java / C #.   -  person Mladen Jablanović    schedule 10.12.2010


Ответы (7)


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

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

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

person TrueWill    schedule 17.12.2010

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

Таким образом, они необходимы, даже если присутствует множественное наследование - наследование касается реализации.

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

person Bozho    schedule 02.12.2010
comment
Я не понимаю. Если документально подтверждено, что он является и должен оставаться интерфейсом, почему можно было бы добавить реализацию? Если утверждается, что сегодня можно сделать что-то семантически правильное, а потом кто-то может изменить это таким образом, чтобы создать большой беспорядок, разве это не верно для каждой языковой особенности? - person Ken; 02.12.2010
comment
Значит ли это, что, например, C ++ страдает отсутствием интерфейсов? - person Mladen Jablanović; 02.12.2010
comment
насчет C ++ - это субъективно. У меня нет опыта, чтобы сказать, страдает ли он. @Ken - чем сложнее чем-то злоупотребить, тем лучше. - person Bozho; 02.12.2010
comment
У кого-нибудь при использовании языка с MI возникают проблемы с другими людьми, добавляющими реализацию в свои интерфейсы? Я даже не слышал об этом. Этот же аргумент можно было бы использовать против неизменяемых классов (кто-то может быть склонен добавить методы мутации!), Но я никогда не видел, чтобы это происходило, и неизменные классы (в системах, которые не имеют такой языковой функции, а именно: большинство из них) чрезвычайно полезны. - person Ken; 02.12.2010
comment
@Ken Очевидно, это полностью выдуманная проблема, оправдание отсутствия MI. Это похоже на фантазию, в которой программисты злоупотребляют перегрузкой операторов, так что operator/ означает сложение, а operator^ означает минимизацию окна. Примерно так же достоверно, как эпизод Симпсона на Хэллоуин. - person curiousguy; 01.11.2011
comment
@Bozho Я нахожусь на этапе изучения C #, теории Java (хотя я кодировал вслепую, не придавая этому большого значения - тогда я понимаю, что теория имеет первостепенное значение, так как без нее я не могу развиваться дальше). Не могли бы вы помочь мне понять, что вы подразумеваете под интерфейсами, определяющими контракты без указания реализаций? на примере? - person aspiring; 15.02.2013

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

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

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

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

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

person Tommy    schedule 10.12.2010
comment
Эти две задачи не эквивалентны, но, несомненно, связаны. Наследование класса подразумевает умение разговаривать, не так ли? - person Mladen Jablanović; 10.12.2010
comment
Да - большее включает меньшее. Но я думаю, что способность различать, где автор ожидает от вас диалога, и где автор ожидает, что вам будут дарованы функциональные возможности, является достаточно большим преимуществом в сложной системе для того, чтобы интерфейсы не были избыточными. - person Tommy; 10.12.2010

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

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

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

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

Но, как отмечали другие, множественное наследование может быть очень сложной задачей для правильного постоянного использования. Я знаю, что не смогу ... и я работал на Мейера, когда он занимался разработкой 2-го издания «Построение объектно-ориентированного программного обеспечения».

person vkraemer    schedule 16.12.2010
comment
Существуют языки, поддерживающие множественное наследование, которые не включают параллельную концепцию интерфейса Java. Знаете ли вы какой-либо пример противоположного - например, язык MI, который имеет отдельную концепцию интерфейса ? - person Mladen Jablanović; 16.12.2010

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

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

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

person Draco Ater    schedule 12.12.2010

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

Все эти языки поставляются с различными утилитами. Для некоторых из них концепция интерфейса - одна из таких утилит. Итак, да, в 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

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

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

person Simon Mourier    schedule 10.12.2010
comment
Но в C # нет MI, верно? Обратите внимание, что я вовсе не сомневаюсь в пользе интерфейсов. - person Mladen Jablanović; 10.12.2010
comment
абсолютно, в C # нет MI. Во всей .NET CLR его нет, но некоторые языки эмулируют его, например Eiffel: msdn.microsoft.com/en-us/library/ms973898.aspx - person Simon Mourier; 11.12.2010

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

person jacknad    schedule 02.12.2010
comment
Тогда почему бы не подавить одиночное наследование? Аргумент не имеет смысла. - person curiousguy; 01.11.2011