stringtranslate.com

Множественное наследование

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

Множественное наследование было спорным вопросом в течение многих лет, [1] [2] при этом оппоненты указывали на его повышенную сложность и двусмысленность в таких ситуациях, как «проблема ромба», где может быть неясно, к какому родительскому классу принадлежит конкретная функция. наследуется, если указанную функцию реализует более одного родительского класса. Эту проблему можно решить разными способами, в том числе с помощью виртуального наследования . [3] Для устранения двусмысленности также были предложены альтернативные методы композиции объектов, не основанные на наследовании, такие как миксины и черты .

Подробности

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

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

Реализации

Языки, поддерживающие множественное наследование, включают: C++ , Common Lisp (через объектную систему Common Lisp (CLOS)), EuLisp (через объектную систему EuLisp TELOS), Curl , Dylan , Eiffel , Logtalk , Object REXX , Scala (с помощью классов- миксинов ). ), OCaml , Perl , POP-11 , Python , R , Raku и Tcl (встроено в версии 8.6 или через Incremental Tcl ( Incr Tcl ) в более ранних версиях [4] [5] ).

Среда выполнения IBM System Object Model (SOM) поддерживает множественное наследование, и любой язык программирования, предназначенный для SOM, может реализовать новые классы SOM, унаследованные от нескольких баз.

Некоторые объектно-ориентированные языки, такие как Swift , Java , Fortran начиная с версии 2003 года , C# и Ruby реализуют одиночное наследование , хотя протоколы или интерфейсы предоставляют некоторые функции настоящего множественного наследования.

PHP использует классы признаков для наследования конкретных реализаций методов. Ruby использует модули для наследования нескольких методов.

Проблема алмазов

Диаграмма наследования класса Diamond.

« Проблема алмаза » (иногда называемая «Смертельным алмазом смерти» [6] ) — это неоднозначность, возникающая, когда два класса B и C наследуются от A, а класс D наследуется как от B, так и от C. Если существует метод в A, который B и C переопределили , а D не переопределяет его, то какую версию метода наследует D: версию B или версию C?

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

Ее называют «проблемой ромба» из-за формы диаграммы наследования классов в этой ситуации. В этом случае класс A находится вверху, B и C по отдельности под ним, а D объединяет их внизу, образуя ромбовидную форму.

смягчение последствий

Языки по-разному решают проблемы повторного наследования.

Языки, допускающие только одиночное наследование , где класс может быть производным только от одного базового класса, не имеют проблемы ромба. Причина этого в том, что такие языки имеют не более одной реализации любого метода на любом уровне цепочки наследования независимо от повторения или размещения методов. Обычно эти языки позволяют классам реализовывать несколько протоколов , называемых интерфейсами в Java. Эти протоколы определяют методы, но не предоставляют конкретных реализаций. Эта стратегия использовалась ActionScript , C# , D , Java , Nemerle , Object Pascal , Objective-C , Smalltalk , Swift и PHP . [13] Все эти языки позволяют классам реализовывать несколько протоколов.

Более того, Ada , C#, Java, Object Pascal, Objective-C, Swift и PHP допускают множественное наследование интерфейсов (называемых протоколами в Objective-C и Swift). Интерфейсы подобны абстрактным базовым классам, которые определяют сигнатуры методов без реализации какого-либо поведения. («Чистые» интерфейсы, такие как интерфейсы Java до версии 7, не допускают никакой реализации или данных экземпляра в интерфейсе.) Тем не менее, даже когда несколько интерфейсов объявляют одну и ту же сигнатуру метода, как только этот метод реализован (определен) в любом месте цепочки наследования он переопределяет любую реализацию этого метода в цепочке над ним (в его суперклассах). Следовательно, на любом уровне цепочки наследования может существовать не более одной реализации любого метода. Таким образом, реализация метода с одним наследованием не демонстрирует проблему ромба даже при множественном наследовании интерфейсов. С введением реализации по умолчанию для интерфейсов в Java 8 и C# 8 все еще возможно создать проблему ромба, хотя это будет проявляться только как ошибка времени компиляции.

Смотрите также

Рекомендации

  1. ^ Каргилл, штат Калифорния (зима 1991 г.). «Противоречие: аргументы против множественного наследования в C++». Вычислительные системы . 4 (1): 69–82.
  2. ^ Уолдо, Джим (весна 1991 г.). «Противоречие: аргументы в пользу множественного наследования в C ++». Вычислительные системы . 4 (2): 157–171.
  3. ^ Шерли, Натанаэль; Дюкасс, Стефан; Ньерстраз, Оскар; Блэк, Эндрю. «Черты характера: составные единицы поведения» (PDF) . Веб.cecs.pdx.edu . Проверено 21 октября 2016 г.
  4. ^ "Инкр Tcl". блог.tcl.tk. _ Проверено 14 апреля 2020 г.
  5. ^ «Введение в язык программирования Tcl». www2.lib.uchicago.edu . Проверено 14 апреля 2020 г.
  6. ^ Мартин, Роберт С. (9 марта 1997 г.). «Java и C++: критическое сравнение» (PDF) . Objectmentor.com . Архивировано из оригинала (PDF) 24 октября 2005 г. Проверено 21 октября 2016 г.
  7. ^ «Стандарт ECMA-367». Ecma-international.org . Проверено 21 октября 2016 г.
  8. ^ «Состояние лямбды». Cr.openjdk.java.net . Проверено 21 октября 2016 г.
  9. Ссылки _ perldoc.perl.org . Проверено 21 октября 2016 г.
  10. ^ Аннотация. «Порядок разрешения методов Python 2.3». Python.org . Проверено 21 октября 2016 г.
  11. ^ «Объединение типов и классов в Python 2.2». Python.org . Проверено 21 октября 2016 г.
  12. ^ "Страница руководства класса" . Tcl.tk. _ 16 ноября 1999 г. Проверено 21 октября 2016 г.
  13. ^ «Интерфейсы объектов — Руководство» . PHP.net . 4 июля 2007 г. Проверено 21 октября 2016 г.

дальнейшее чтение

Внешние ссылки