Читаем Основы объектно-ориентированного программирования полностью

Это правило отражает одну из важных характеристик наследования: сказать, что B наследует A - это утверждать, что каждый экземпляр B является также экземпляром A. Вследствие этого всякое выраженное инвариантом ограничение целостности, применимое к экземплярам A, будет также применимо и к экземплярам B.

В нашем примере второе предложение (at_least_three) инварианта POLYGON утверждает, что число сторон должно быть не менее трех, оно является следствием предложения four_sides из инварианта класса RECTANGLE, которое требует, чтобы сторон было ровно четыре.

<p>Наследование и конструкторы</p>

Ранее не показанная процедура создания (конструктор) для класса POLYGON может иметь вид

make_polygon (vl: LINKED_LIST [POINT]) is

-- Создание по вершинам из vl.

require

vl.count >= 3

do

...Инициализация представления многоугольника по элементам из vl ...

ensure

-- vertices и vl состоят из одинаковых элементов (это можно выразить

формально)

end

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

Ей дано собственное имя make_polygon, чтобы избежать конфликта имен при ее наследовании классом RECTANGLE, у которого имеется собственная процедура создания make. Мы не рекомендуем так делать в общем случае, в следующей лекции будет показано, как давать процедуре создания класса POLYGON стандартное имя make, а затем использовать переименование в предложении о наследовании класса RECTANGLE, чтобы предотвратить коллизию имен.

Приведенная выше процедура создания класса RECTANGLE имеет четыре аргумента: точку, служащую центром, длины двух сторон и ориентацию. Отметим, что компонент vertices применим к прямоугольникам, поэтому процедура создания для RECTANGLE создает список вершин vertices (четыре угла вычисляются по центру, длинам сторон и ориентации).

Общая процедура создания для многоугольников не удобна прямоугольникам, так как приемлемы только списки из четырех элементов, удовлетворяющих инварианту класса RECTANGLE. Процедура создания для прямоугольников, в свою очередь, не годится для произвольных многоугольников. Это обычное дело: процедура создания родителя не подходит для наследника. Нельзя гарантировать, что она будет удовлетворять его новому инварианту.

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

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

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

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

В некоторых случаях родительский конструктор подходит и для наследника. Тогда его просто нужно указать в предложении creation:

class B inherit

A

creation

make

feature

...

где процедура make наследуется без изменений от класса A, у которого она также указана в предложении creation.

<p>Пример иерархии</p>

В конце обсуждения полезно рассмотреть пример POLYGON-RECTANGLE в контексте более общей иерархии типов геометрических фигур.

Рис. 14.2.  Иерархия типов фигур

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

Рядом с классами указаны их разные компоненты. Символ "++" означает "переопределено", а символы "+" и "*" будут объяснены далее.

Ранее для простоты RECTANGLE был наследником класса POLYGON. Поскольку указанная классификация основана на числе вершин, то представляется разумным ввести промежуточный класс QUADRANGLE для четырехугольников на том же уровне, что и классы TRIANGLE, PENTAGON и т. п. Тогда компонент diagonal (диагональ) можно переместить на уровень класса QUADRANGLE.

Перейти на страницу:

Похожие книги