
- •Основные механизмы и положения объектно-ориентированного программирования
- •5.1. Инкапсуляция
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Interface
- •Implementation
- •5.2. Наследование
- •Interface
- •Implementation
- •Interface
- •Implementation
- •5.3. Жизненный цикл экземпляра класса
- •Interface
- •Implementation
- •Inherited;
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Interface
- •5.4. Полиморфизм
- •5.4.1. Совместимость объектов
- •Класс в Экземпляр
- •Interface Type
- •Implementation
- •Interface
- •Implementation
- •If Figure is tLine
- •Interface
- •Implementation
- •Interface
- •Implementation
- •IColor: Integer;
5.2. Наследование
5.2.1. Основы наследования
Один из основных механизмов объектно-ориентированного программирования — наследование — построение нового класса на основе ранее описанного класса. Полученные в результате наследования классы называются классами-наследниками (или дочерними классами), а классы на основе которых они построены — классами-родителями (или родительскими классами). При наследовании дочерний класс приобретает все свойства и методы родительского класса и имеет доступ к любому его элементу, за исключением описанных с областью видимости private.
При описании дочернего класса с использованием наследования имя родительского класса указывается в скобках после ключевого слова с1ass| в заголовке интерфейсной части описываемого класса:
Туре
<Имя класса> = class (<Имя родительского класса>) {Заголовок описания}
......... {Описание собственных свойств и методов}
End;
Класс-наследник может быть описан на основе любого другого класса, вне зависимости от того, является ли родительский класс в свою очередь дочерним. Более того, все классы в Delphi являются наследниками от класса TObject, даже если это явно не указывается.
Класс TObject инкапсулирует основные методы и свойства, связанные с общим поведением объектов. К ним относятся такие как создание, инициализация и разрушение объектов; поддержка идентификации их принадлежности к классу во время выполнения программы и многие другие, связанные с интеграцией объектов, созданных в Delphi, в среду выполнения программы, то есть операционную систему. Таким образом, экземпляры любого класса в Delphi автоматически приобретают все эти возможности.
5.2.2. Переопределение методов
Часто встречается ситуация, когда один или несколько методов дочернего класса должны работать не так, как в родительском классе. В качестве примера можно привести класс TGeomFigure, представляющий собой абстрактную геометрическую фигуру, и имеющий метод Draw для ее рисования. Наследниками этого класса могли бы быть классы TCircle для работы с окружностями, TLine для работы с линиями, и так далее.
Очевидно, что все дочерние классы в такой ситуации должны изменить метод Draw, чтобы корректно отображать фигуры, которым они соответствуют. Изменение функциональности унаследованных методов в дочерних классах называется переопределением методов.
Механизм переопределения
Для переопределения метода, реализованного в объекте-родителе, следует:
♦ указать его заголовок в интерфейсной части описания дочернего класса без изменения имени, списка параметров и возвращаемого значения (если метод является функцией);
♦ указать после заголовка метода ключевое слово override. Если ключевое слово override не указано, то метод не переопределяется.
♦ реализовать метод (создать программный код) в описательной части объекта по обычным правилам. При этом в заголовке метода ключевое слово override не указывается.
Чтобы метод мог быть переопределен в дочерних классах, он должен быть помечен ключевыми словами virtual или dynamic в интерфейсной части класса-родителя. Ключевое слово virtual указывает на то, что метод должен быть занесен в так называемую таблицу виртуальных методов ТВМ), а ключевое слово dynamic на то, что метод должен быть найден ло имени в дереве родительских объектов.
Разница между использованием virtual и dynamic заключается в направлении оптимизации компилятором вызовов переопределяемых методов. Методы, помеченные virtual, оптимизируются по скорости, а zynamic-методы по размеру программного кода. В большинстве случаев рекомендуется использование виртуальных методов, а использование динамических методов целесообразно при высоких степенях вложенности cвязей родитель-наследник.
Приведем описание класса TwoNums с двумя свойствами а и Ь, и методом GetResult, возвращающим сумму свойств. Далее, от этого класса эпишем наследника ThreeNums, имеющего уже три свойства — а, b и с, и переопределяющего метод GetResult таким образом, чтобы возвращать сумму не двух, а трех чисел (листинг 5.10).
Листинг 5.10. Использование переопределения
Unit Overriding1;