Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Обобщение и наследование



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

Отношения наследования надо устанавливать, если для двух классов справедливым является следующее высказывание: «класс В является разновидностью класса А» (класс В “ is-a ” класс А). Этим отношение наследования принципиально отличается от агрегации и композиции. Например, если двигатель есть часть автомобиля, то уж никак двигатель не является разновидностью автомобиля. С другой стороны, автомобиль есть разновидность транспортного средства, но никак не его часть!

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

 
 


в подклассе не определяются
унаследованные свойства
унаследованные методы
новые свойства
новые методы
переопределенные методы
Дочерний подкласс 2
унаследованные свойства
унаследованные методы
новые свойства
новые методы
переопределенные методы
Дочерний подкласс 1

Дочерний подкласс, в свою очередь, может выступать в качестве базового родительского класса, на основе которого можно создать свои дочерние подклассы. В итоге получается иерархическая древовидная структура классов, часто называемая библиотекой классов. На верхних уровнях этой иерархии находятся наиболее общие классы с относительно небольшим числом свойств и методов. Чем ниже класс в иерархии, тем больше он имеет свойств и методов и, тем самым, носит более конкретный характер. Классы верхних уровней часто объявляются абстрактными. Эти классы нужны для придания общности нижележащим подклассам.


Рассмотренный тип наследования называют простым наследованием. В этом случае дочерние подклассы могут иметь только одного родителя. Если родителей может быть несколько, то наследование называют множественным. Множественное наследование в чистом виде реализовано только в языке С++. В случае множественного наследования вместо древовидной иерархии возникает иерархия в виде ориентированного графа:

 
 


Множественное наследование является очень мощным механизмом, но при его практическом использовании появляются трудности, связанные с неоднозначностью путей наследования. По этой причине в языке Java и в языках платформы.NET реализовано только простое наследование, но в качестве альтернативного механизма предложен более простой, по сравнению с множественным наследованием, механизм интерфейсных классов (см. раздел 4.1 пособия).

В дальнейшем основное внимание будет уделено библиотекам классов, которые построены на принципе простого наследования. Именно так построены стандартные библиотеки классов, поддерживающие языки Java, Delphi Pascal и платформу.NET. В этих библиотеках на самом верхнем уровне находится единственный класс, который является общим предком абсолютно любых классов, как стандартных, так и создаваемых программистом при разработке объектной программы. В этом классе объявляются свойства и методы, наследуемые всеми классами. В языках Java и С# этот класс называют Object, в Delphi Pascal – TObject. Несмотря на общность названия, структура этих классов в разных языках различная.

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

Механизм наследования между классами в разных языках включается очень легко и практически одинаково: имя родительского класса прописывается в заголовке нового класса.

В языке Delphi Pascal:

type

TChild = class (TParent)

private

новые свойства;

public

новые методы;

end;

Если родительский класс не задан, то компилятор автоматически в качестве родителя подставляет класс TObject. Тем самым все новые классы включаются в общую иерархию, что позволяет использовать ряд мощных механизмов, рассматриваемых в следующих разделах пособия.

В языке Java:

class Child extends Parent

{ новые свойства;

новые методы;

};

Здесь также при отсутствии родительского класса автоматически подставляется базовый класс Object и тем самым все классы включаются в общую иерархию.

В языке С++:

class Child: Parent1, Parent2, Parent3 // список родителей

{ новые свойства;

новые методы;

};

В качестве примера рассмотрим построение двух небольших библиотек классов:

· иерархия классов для основных графических примитивов;

· иерархия классов для основных структур данных.

Необходимо отметить, что построение иерархии классов не всегда бывает простым и очевидным и часто может быть выполнено различными способами.

Пример 1. На верхний уровень создаваемой иерархии необходимо поместить общий класс фигур. Этот класс целесообразно объявить абстрактным. Для фигуры надо ввести два свойства, которые затем будут наследоваться всеми подклассами. Эти свойства – координаты базовой точки – должны иметь любые примитивы-фигуры. В классе фигур можно ввести следующие абстрактные методы: показ фигуры (метод Show), перемещение базовой точки (метод MoveTo). Можно в классе ввести конструктор, но использовать его не для создания объектов (это запрещено для абстрактных классов), а для инициализации свойств-координат. Подклассами класса фигур можно сделать:

· класс Окружность (безусловно, окружность есть разновидность фигуры);

· класс Четырехугольник (это тоже разновидность фигуры).

В свою очередь, для класса Окружность можно создать два подкласса:

· класс Эллипс (с некоторыми оговорками эллипс можно считать сплюснутой окружностью);

· класс Дуга (тоже с некоторыми оговорками можно считать, что дуга – это разновидность окружности, для которой заданы начальный и конечный угол).

Графическое представление иерархии классов с использованием элементов языка UML выглядит следующим образом.

 
 


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

Класс ADS
Count: integer
Create; Add; Delete; Find; GetCount; IsEmpty;

 
 


При наследовании свойств и методов немного изменяется механизм доступа к элементам классов. Закрытые элементы класса по-прежнему доступны для прямого использования только объектам данного класса. Важно отметить, что эти элементы остаются закрытыми и для дочерних подклассов, т.е. закрытые элементы базового класса присутствуют в дочерних классах, но доступ к ним разрешен только через открытые методы родителя. Кроме двух стандартных уровней доступа (private и public) введен промежуточный уровень, описываемый директивой protected. Элементы с этой директивой, называемые по-русски защищенными, доступны для прямого использования в любых дочерних подклассах и только в них.

Большое значение при использовании наследования имеет правильное создание объектов дочерних классов. Поскольку дочерние подклассы практически всегда содержат больше свойств, чем их родители, то при создании дочернего объекта необходимо правильно инициализировать унаследованные свойства. За установку унаследованных свойств отвечает родительский конструктор, поэтому конструктор дочернего класса должен начинать свою работу с вызова конструктора родительского класса. Для этого используются специальные синтаксические приемы, отличающиеся для различных языков программирования.

В языке DP для вызова родительского конструктора используется директива inherited:

inherited Create ();

В языке Java – директива super:

super (параметры);

В языке С++ вызов родительского конструктора можно вставить в заголовок дочернего конструктора:

Circle::Circle (ax, ay, ar): Figure (ax, ay);

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

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

· координаты базовой точки x и y;

· радиус окружности R;

· начальный и конечный угол дуги a1 и a2.





Дата публикования: 2014-11-02; Прочитано: 1583 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.01 с)...