1.1.2. Наследование

1.1.2. Наследование

Мы подходим к одной из самых сильных сторон ООП — наследованию. Наследование —- это механизм, позволяющий расширять ранее определенную сущность путем добавления новых возможностей. Короче говоря, наследование - это способ повторного использования кода. (Простой и эффективный механизм повторного использования долго был Святым Граалем в информатике. Много десятилетий назад его поиски привели к изобретению параметризованных процедур и библиотек. ООП - лишь одна из последних попыток реализации искомого.)

Обычно наследование рассматривается на уровне класса. Если нам необходим какой-то класс, а в наличии имеется более общий, то можно определить свой класс так, чтобы он наследовал поведение уже существующего. Предположим, например, что есть класс Polygon, описывающий выпуклые многоугольники. Тогда класс прямоугольника Rectangle можно унаследовать от Polygon. При этом Rectangle будет иметь все атрибуты и методы класса Polygon. Так, может уже быть написан метод, вычисляющий периметр путем суммирования длин всех сторон. Если все было реализовано правильно, этот метод автоматически будет работать и для нового класса; переписывать код не придется.

Если класс B наследует классу A, мы говорим, что B является подклассом A, а A — суперкласс B. По-другому говорят, что А — базовый или родительский класс, а B — производный или дочерний класс.

Как мы видели, производный класс может трактовать методы своего базового класса как свои собственные. С другой стороны, он может переопределить метод базового класса, предоставив иную его реализацию. Кроме того, в большинстве языков есть возможность вызвать из переопределенного метода метод базового класса с тем же именем. Иными словами, метод fоо класса B знает, как вызвать метод foo класса A. (Любой язык, не предоставляющий такого механизма, можно заподозрить в отсутствии истинной объектной ориентированности.) То же верно и в отношении атрибутов.

Отношение между классом и его суперклассом интересно и важно, обычно его называют отношением «является». Действительно, квадрат Square «является» прямоугольником Rectangle, а прямоугольник Rectangle «является» многоугольником Polygon и т.д. Поэтому, рассматривая иерархию наследования (а такие иерархии в том или ином виде присутствуют в любом объектно-ориентированном языке), мы видим, что в любой ее точке специализированные сущности «являются» подклассами более общих. Отметим, что это отношение транзитивно, — если обратиться к предыдущему примеру, то квадрат «является» многоугольником. Однако отношение «является» не коммутативно — каждый прямоугольник есть многоугольник, но не каждый многоугольник — прямоугольник.

Это подводит нас к теме множественного наследования. Можно представить себе класс, который наследует нескольким классам. Например, классы Dog (Собака) и Cat (Кошка) могут наследовать классу Mammal (Млекопитающее), а Sparrow (Воробей) и Raven (Ворон) — классу WingedCreature (Крылатое). Но как быть с классом Bat (ЛетучаяМышь)? Он с равным успехом может наследовать и Mammal, и WingedCreature! Это хорошо согласуется с нашим жизненным опытом, ведь многие вещи можно отнести не к одной категории, а сразу к нескольким, не вложенным друг в друга.

Множественное наследование, вероятно, наиболее противоречивая часть ООП. Некоторые указывают на потенциальные неоднозначности, требующие разрешения. Например, если в обоих классах Mammal и WingedCreature имеется атрибут size (размер) или метод eat (есть), то какой из них имеется в виду, когда мы обращаемся к нему из объекта класса Bat? С этой трудностью тесно связана проблема ромбовидного наследования; она называется так из-за формы диаграммы наследования, возникающей, когда оба суперкласса наследуют одному классу. Представьте себе, что классы Mammal и WingedCreature наследуют общему предку Organism (Организм); тогда иерархия наследования от Organism к Bat будет иметь форму ромба. Но как быть с атрибутами, которые оба промежуточных класса наследуют от своего родителя? Получает ли Bat две копии? Или они должны быть объединены в один атрибут, поскольку все равно заимствованы у общего предка?

Это скорее проблемы проектировщика языка, а не программиста. В разных объектно-ориентированных языках они решаются по-разному. Иногда вводятся правила, согласно которым какое-то одно определение атрибута «выигрывает». Либо же предоставляется возможность различать одноименные атрибуты. Иногда даже язык позволяет вводить псевдонимы или переименовывать идентификаторы. Многими это рассматривается как аргумент против множественного наследования — о механизмах разрешения подобных конфликтов имен нет единого мнения, поэтому все они «языкозависимы». В языке C++ предлагается минимальный набор средств для разрешения неоднозначностей; механизмы языка Eiffel, наверное, получше, а в Perl проблема решается совсем по-другому.

Есть и альтернатива — полностью запретить множественное наследование. Такой подход принят в языках Java и Ruby. На первый взгляд, это даже не назовешь компромиссным решением, но, вскоре мы убедимся, что все не так плохо, как кажется. Мы познакомимся с приемлемой альтернативой традиционному множественному наследованию, но сначала обсудим полиморфизм — еще одно понятие из арсенала ООП.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

2. Наследование

Из книги Информатика и информационные технологии: конспект лекций автора Цветкова А В

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


26. Наследование

Из книги Информатика и информационные технологии автора Цветкова А В

26. Наследование Наследование – это процесс порождения новых типов-потомков от существующих типов-родителей, при этом потомок получает (наследует) от родителя все его поля и методы.Тип-потомок, при этом, называется наследником или порожденным (дочерним) типом. А тип,


Наследование

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

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


Наследование

Из книги Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT автора Фролов Александр Вячеславович

Наследование Пожалуй, самая важная возможность, предоставляемая программисту средствами языка Си++, заключается в механизме наследования. Вы можете наследовать от определенных ранее классов новые производные классы. Класс, от которого происходит наследование,


Единичное наследование

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Единичное наследование В случае единичного наследования порожденный класс наследуется только от одного базового класса. Рисунок 1.1 отражает единичное наследование классов. Единичное наследование является наиболее распространенным методом наследования. Библиотека


Наследование инварианта

Из книги Программирование на языке Ruby [Идеология языка, теория и практика применения] автора Фултон Хэл

Наследование инварианта Хотелось бы указать инвариант класса RECTANGLE, который говорил бы, что число сторон прямоугольника равно четырем и что длины сторон последовательно равны side1, side2, side1 и side2.У класса POLYGON также имеется инвариант, который применим и к его


Наследование и конструкторы

Из книги C++ для начинающих автора Липпман Стенли

Наследование и конструкторы Ранее не показанная процедура создания (конструктор) для класса POLYGON может иметь видmake_polygon (vl: LINKED_LIST [POINT]) is-- Создание по вершинам из vl.requirevl.count >= 3do...Инициализация представления многоугольника по элементам из vl ...ensure-- vertices и vl состоят из


Наследование и децентрализация

Из книги Описание языка PascalABC.NET автора Коллектив РуБоард

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


У14.4 Наследование без классов

Из книги автора

У14.4 Наследование без классов В этой лекции были представлены два взгляда на наследование: будучи модулем, класс-наследник предлагает службы своего родителя плюс еще некоторые, будучи типом, он реализует отношение "является" (каждый экземпляр наследника является также


Структурное наследование

Из книги автора

Структурное наследование Множественное наследование просто необходимо, когда необходимо задать для класса ряд дополнительных свойств, помимо свойств, заданных базовой абстракцией.Рассмотрим механизм создания объектов с постоянной структурой (способных сохраняться


Дублируемое наследование

Из книги автора

Дублируемое наследование Дядюшка Жак: С кем желаете Вы говорить, сударь, с конюхом или с поваром? Ибо я у Вас и то, и другое. Мольер, "Скупой" Дублируемое наследование (repeated inheritance) возникает, когда класс является потомком другого класса более чем на одном пути наследования.


Наследование и утверждения

Из книги автора

Наследование и утверждения Следствия красоты базисных идей:[x]. Связь наследования с утверждениями и Проектированием по Контракту.[x]. Глобальная структура наследования, где все классы согласованы.[x]. Замороженные компоненты, для которых не применим принцип


1.1.2. Наследование

Из книги автора

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


19.2. Исключения и наследование

Из книги автора

19.2. Исключения и наследование Обработка исключений – это стандартное языковое средство для реакции на аномальное поведение программы во время выполнения. C++ поддерживает единообразный синтаксис и стиль обработки исключений, а также способы тонкой настройки этого


Наследование

Из книги автора

Наследование Класс может быть унаследован от другого класса. Класс, от которого наследуют, называют базовым классом (надклассом, предком), а класс, который наследуется, называется производным классом (подклассом, потомком). При наследовании все поля, методы и свойства


Наследование конструкторов

Из книги автора

Наследование конструкторов Правила наследования конструкторов - достаточно сложные. В разных языках программирования приняты разные решения на этот счет. В частности, в Delphi Object Pascal все конструкторы наследуются. В .NET, напротив, конструкторы не наследуются. Причина такого