Я знаю, что в Java и C # множественное наследование запрещено. Во многих книгах прямо говорится, что множественное наследование недопустимо. Но это можно реализовать с помощью интерфейсов. Ничего не обсуждается, почему это запрещено. Кто-нибудь может сказать мне, почему это запрещено?
c#
java
language-design
multiple-inheritance
Абдулсаттар Мохаммед
источник
источник
Ответы:
Короткий ответ: потому что разработчики языка решили не делать этого.
По сути, казалось, что дизайнеры .NET и Java не допускают множественного наследования, потому что они рассуждали, что добавление MI усложняет языки, но дает слишком мало преимуществ .
Для более увлекательного и подробного чтения в сети доступны статьи с интервью с некоторыми разработчиками языков. Например, для .NET Крис Брамм (который работал в MS над CLR) объяснил причины, по которым они решили не делать этого:
Вы можете прочитать всю статью здесь.
Для Java вы можете прочитать эту статью :
источник
Множественное наследование реализации недопустимо.
Проблема в том, что компилятор / среда выполнения не может понять, что делать, если у вас есть классы Cowboy и Artist, оба с реализациями для метода draw (), а затем вы пытаетесь создать новый тип CowboyArtist. Что происходит, когда вы вызываете метод draw ()? Кто-то лежит мертвый на улице, или у вас есть прекрасная акварель?
Я считаю, что это называется проблемой наследования двойного ромба.
источник
Причина: Java очень популярна, и ее легко кодировать из-за ее простоты.
То, что когда-либо казалось разработчикам Java трудным и сложным для понимания программистами, они старались избегать. Одним из таких видов собственности является множественное наследование.
Проблема с множественным наследованием: проблема с алмазом.
Пример :
Это неоднозначность, существующая в алмазной проблеме.
Решить эту проблему возможно, но она создает больше путаницы и сложностей для программиста при ее чтении. Это создает больше проблем, чем пытается решить.
Примечание . Но в любом случае вы всегда можете реализовать множественное наследование косвенно, используя интерфейсы.
источник
Потому что у Java философия дизайна сильно отличается от C ++. (Я не собираюсь здесь обсуждать C #.)
При разработке C ++ Страуструп хотел включить полезные функции, независимо от того, как они могут быть использованы неправильно. Можно сильно облажаться с множественным наследованием, перегрузкой операторов, шаблонами и различными другими функциями, но с ними также можно делать очень хорошие вещи.
Философия дизайна Java - сделать упор на безопасность языковых конструкций. В результате есть вещи, которые делать намного более неудобно, но вы можете быть гораздо более уверены в том, что код, на который вы смотрите, означает то, что вы думаете.
Кроме того, Java в значительной степени была реакцией C ++ и Smalltalk, наиболее известных объектно-ориентированных языков. Существует множество других объектно-ориентированных языков (Common Lisp был фактически первым, который был стандартизирован), с различными системами объектно-ориентированного программирования, которые лучше справляются с MI.
Не говоря уже о том, что MI на Java вполне возможно, используя интерфейсы, композицию и делегирование. Он более явный, чем в C ++, и, следовательно, более неуклюж в использовании, но даст вам то, что вы с большей вероятностью поймете с первого взгляда.
Здесь нет правильного ответа. Есть разные ответы, и какой из них лучше для конкретной ситуации, зависит от приложений и индивидуальных предпочтений.
источник
Основная (хотя ни в коем случае не единственная) причина, по которой люди избегают МИ, - это так называемая «проблема алмаза», приводящая к двусмысленности в вашей реализации. Эта статья в Википедии обсуждает это и объясняет лучше, чем я. MI также может привести к более сложному коду, и многие разработчики объектно-ориентированных приложений утверждают, что вам не нужен MI, и если вы его используете, ваша модель, вероятно, неверна. Я не уверен, что согласен с этим последним пунктом, но всегда сохранять простоту - хороший план.
источник
В C ++ множественное наследование было серьезной головной болью при неправильном использовании. Чтобы избежать этих популярных проблем с дизайном, в современных языках (java, C #) вместо этого было принудительно реализовано «наследование» нескольких интерфейсов.
источник
Множественное наследование
Таким образом, можно считать разумным не включать множественное наследование в язык Java.
источник
Другая причина заключается в том, что одинарное наследование делает приведение типов тривиальным, не генерируя никаких инструкций ассемблера (кроме проверки совместимости типов, где это необходимо). Если у вас было множественное наследование, вам нужно было бы выяснить, где в дочернем классе начинается определенный родитель. Так что производительность, безусловно, является преимуществом (хотя и не единственным).
источник
В старые времена (70-е годы), когда информатика была больше наукой и менее массовым производством, у программистов было время подумать о хорошем дизайне и хорошей реализации, и в результате продукты (программы) имели высокое качество (например, дизайн TCP / IP и реализация). В настоящее время, когда все программируют, а менеджеры меняют спецификации до истечения крайних сроков, трудно отследить тонкие проблемы, подобные описанной в ссылке на википедию из сообщения Стива Хая; поэтому «множественное наследование» ограничено конструкцией компилятора. Если вам это нравится, вы все равно можете использовать C ++ .... и иметь всю свободу, которую хотите :)
источник
Я отношусь к утверждению, что «Множественное наследование запрещено в Java», с долей скепсиса.
Множественное наследование определяется, когда «Тип» наследуется от более чем одного «Типа». И интерфейсы также классифицируются как типы по своему поведению. Итак, у Java есть множественное наследование. Просто так безопаснее.
источник
Динамическая загрузка классов затрудняет реализацию множественного наследования.
На самом деле в java они избежали сложности множественного наследования, вместо этого используя единое наследование и интерфейс. Сложность множественного наследования очень высока в ситуации, описанной ниже.
алмазная проблема множественного наследования. У нас есть два класса B и C, наследующие от A. Предположим, что B и C переопределяют унаследованный метод и предоставляют свою собственную реализацию. Теперь D наследуется как от B, так и от C, выполняя множественное наследование. D должен унаследовать этот переопределенный метод, jvm не может решить, какой переопределенный метод будет использоваться?
В C ++ для обработки используются виртуальные функции, и мы должны делать это явно.
Этого можно избежать, используя интерфейсы, тела методов отсутствуют. Интерфейсы не могут быть созданы - они могут быть реализованы только классами или расширены другими интерфейсами.
источник
На самом деле множественное наследование будет усложняться, если унаследованные классы имеют одинаковую функцию. т.е. у компилятора возникнет путаница, которую нужно выбрать (проблема с ромбами). Таким образом, в Java эта сложность устранена и предоставлен интерфейс для получения такой функциональности, как множественное наследование. Мы можем использовать интерфейс
источник
В Java есть понятие, то есть полиморфизм. В java есть 2 типа полиморфизма. Есть перегрузка метода и переопределение метода. Среди них переопределение метода происходит с отношениями суперкласса и подкласса. Если мы создаем объект подкласса и вызываем метод суперкласса, и если подкласс расширяет более одного класса, какой метод суперкласса следует вызывать?
Или при вызове конструктора суперкласса
super()
, какой конструктор суперкласса будет вызван?Это решение невозможно из-за текущих возможностей Java API. поэтому множественное наследование в java запрещено.
источник
Множественное наследование не разрешено в Java напрямую, но разрешено через интерфейсы.
Причина:
Множественное наследование: вносит большую сложность и неоднозначность.
Интерфейсы: интерфейсы - это полностью абстрактные классы в Java, которые предоставляют вам единообразный способ правильно разграничить структуру или внутреннюю работу вашей программы из общедоступного интерфейса, что приводит к большей гибкости и возможности многократного использования кода, а также к большему контролю. о том, как вы создаете и взаимодействуете с другими классами.
Точнее, они представляют собой специальную конструкцию в Java с дополнительной характеристикой, позволяющей выполнять своего рода множественное наследование, то есть классы, которые могут быть преобразованы в более чем один класс.
Возьмем простой пример.
Предположим, что существует 2 суперкласса класса A и B с одинаковыми именами методов, но с разными функциями. В следующем коде с ключевым словом (extends) множественное наследование невозможно.
Но через интерфейсы с ключевым словом (реализация) множественное наследование возможно.
источник
Вы можете найти ответ по этой ссылке документации
Если разрешено множественное наследование и когда вы создаете объект, создавая экземпляр этого класса, этот объект будет наследовать поля от всех суперклассов класса. Это вызовет две проблемы.
Что, если методы или конструкторы из разных суперклассов создают экземпляр одного и того же поля?
Какой метод или конструктор будет иметь приоритет?
Несмотря на то, что теперь разрешено множественное наследование состояния, вы все же можете реализовать
Множественное наследование типа : способность класса реализовывать более одного интерфейса.
Множественное наследование реализации (через методы по умолчанию в интерфейсах): возможность наследовать определения методов из нескольких классов
Обратитесь к соответствующему вопросу SE для получения дополнительной информации:
Неоднозначность множественного наследования с интерфейсом
источник
В C ++ класс может наследовать (прямо или косвенно) более чем от одного класса, что называется множественным наследованием. .
Однако C # и Java ограничивают классы одним наследованием, которое каждый класс наследует от одного родительского класса.
Множественное наследование - это полезный способ создания классов, которые объединяют аспекты двух разрозненных иерархий классов, что часто случается при использовании разных структур классов в одном приложении.
Если две структуры определяют свои собственные базовые классы для исключений, например, вы можете использовать множественное наследование для создания классов исключений, которые могут использоваться с любой структурой.
Проблема множественного наследования в том, что оно может привести к неоднозначности. Классический пример - это когда класс наследуется от двух других классов, каждый из которых наследуется от того же класса:
В этом примере
flag
член данных определяется какclass A
. Ноclass D
нисходитclass B
иclass C
, которые оба происходят изA
, так что по сути две копии изflag
доступны , потому что два экземпляраA
вD
иерархии классов «S. Какой из них вы хотите установить? Компилятор будет жаловаться , что ссылка наflag
инD
является неоднозначной . Одно исправление - явное устранение неоднозначности ссылки:Еще одно исправление - объявить B и C как
virtual base classes
, что означает, что в иерархии может существовать только одна копия A, что устраняет любую двусмысленность.Другие сложности существуют с множественным наследованием, например порядок, в котором базовые классы инициализируются при построении производного объекта, или способ непреднамеренного скрытия членов от производных классов. Чтобы избежать этих сложностей, некоторые языки ограничиваются более простой моделью одиночного наследования.
Хотя это значительно упрощает наследование, оно также ограничивает его полезность, поскольку только классы с общим предком могут совместно использовать поведение. Интерфейсы несколько смягчают это ограничение, позволяя классам в разных иерархиях предоставлять общие интерфейсы, даже если они не реализованы путем совместного использования кода.
источник
Представьте себе этот пример: у меня есть класс
Shape1
У него есть
CalcualteArea
метод:Есть еще один класс
Shape2
, у которого также есть тот же методТеперь у меня есть дочерний класс Circle, он является производным от Shape1 и Shape2;
Теперь, когда я создаю объект для Circle и вызываю метод, система не знает, какой метод вычисления площади следует вызвать. У обоих одинаковые подписи. Так что компилятор запутается. Вот почему множественное наследование не допускается.
Но интерфейсов может быть несколько, потому что интерфейсы не имеют определения метода. Даже у обоих интерфейсов есть один и тот же метод, оба из них не имеют никакой реализации, и всегда будет выполняться метод в дочернем классе.
источник