Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
1
Добавлен:
14.04.2019
Размер:
181.25 Кб
Скачать

Проблема множественности иерархий Агрегирование

Мышление в терминах иерархий, уточнение строения и поведения, естественно для человеческого мышления. Но в несистематизированных областях построение иерархии – очень трудное дело, даже в хорошо систематизированных областях. Проектирование классов занимает до 80% всего времени разработки. Даже в систематизированных областях таких иерархий может быть очень много. Не деле для полной идентификации объектов необходимо, чтобы любые два объекта попадали в различные классы при какой-то классификации (в какой-то иерархии).

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

Children=class

Mum: cMum;

Dad: cDad;

end;

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

Абстрактные методы и именованные интерфейсы

Вспомним пример с животными. Нужно ли было реализовывать в классе Animal метод Move, который по смыслу, в любом случае, должен был быть переписан в классах-потомках? Можно было просто оставить эту реализацию пустой, но это означало бы лишь, что этот метод может, но не должен обязательно, быть реализован в классах-потомках. Отношение необходимости такой реализации оформляется с помощью опции abstract (абстрактный метод).

Нетрудно представить пример абстрактного класса, в котором нет полей, а все методы абстрактны. Такой класс по семантике (не синтаксису и не происхождению, отличному от чистого ООП) сопоставили именованному интерфейсу.

Основная идея – возможность ссылки на интерфейс. На деле несколько интерфейсов.

type

(имя интерфейса)= interface (ссылка на интерфейс-предок)

[опции]

(список методов и свойств (не полей!))

end;

Заголовки процедур в этом случае не имеют никаких привычных опций, все они по умолчанию public. Спецификации static, virtual, dynamic и так далее отсутствуют. Интерфейсы не могут быть инициализированы (то есть не существует переменных такого типа), поэтому интерфейсы не имеют конструкторов и деструкторов. Класс реализует интерфейс, если в нём реализуются все его методы. Один класс может реализовывать несколько интерфейсов. В случае множественных иерархий нужно выделять одну, как основную (существительные), а много других – как вторичные (уточняющие).

Пример. Иерархия животных основная по строению, по передвижению – вторичная.

type Animals=classend;

Mammals=class(Animals) … end;

Fishes=class(Animals) … end;

Birds=class(Animals) … end;

FlyAble=interface

procedure Fly(P);

end;

RunAble=interface

procedure Run(P);

end;

SwimAble=interface

procedure Swim(P);

end;

Elephant=class(Mammals, RunAble)

***

end;

{Класс Elephant не обязан определять методы класса Mammals, но обязан реализовать интерфейс RunAble (реализация процедуры Run)}

Dolphin=class(Mammal, SwimAble)

***

end;

Duck=class (Birds, SwimAble, RunAble, FlyAble)

***

end;

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

Что является значением метода?

С точки зрения логики – реализация (определение). С точки зрения реализации – ссылка на определение (в терминах Паскаля – значение процедурного типа). Например, мы можем реализовать метод присваиванием ему имени, уже определённого к этому времени.

NewMethod=OldMethod – такое присваивание называется отображением (mapping).

Наряду с агрегированием в качестве множественного наследования этот способ может трактоваться как определение, собственно, наследования по умолчанию.

Что делает понятие интерфейса независимой и полной схемой объектного программирования?

К сожалению, понятие класса и его интерфейса не очень чётко разведены в Delphi. Ранее мы трактовали функцию as как явное приведение типов: (объект) as (класс). Ту же функцию можно употреблять как (объект as имя интерфейса).Method, как если бы этот объект имел только этот интерфейс.