Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование лекции.doc
Скачиваний:
49
Добавлен:
12.11.2019
Размер:
5.53 Mб
Скачать

10.Наследование и полиморфизм

Наследование – еще один фундаментальный принцип объектно-ориентированного подхода. Термин "наследование" (inheritance) не совсем точно отражает смысл происходящего. В обычной жизни наследник получает что-то только после кончины наследодателя. Программирование заметно более гуманно – здесь объект-потомок получает свойства и методы объекта-родителя еще при его жизни.

Наследование позволяет создавать производные объектные типы данных (классы) на основе уже существующих. При этом производные классы наследуют свойства и методы базового класса и добавляют к ним новые (Рис. 10 .21).

Рис. 10.21. Принцип наследования.

Рассмотрим классический пример наследования – объект, моделирующий работу автомобиля. Очевидно, любой автомобиль – и "Запорожец", и "Мерседес" – имеют ряд общих свойств и методов. Перечислим их:

TYPE Tvehicle=CLASS PRIVATE power:WORD; { мощность } speed: WORD; { скорость } gear: BYTE; { передача } engineon: BOOLEAN; { двигатель вкл/выкл } fuelcons: REAL; { расход топлива } PROCEDURE StartEngine; PROCEDURE ChangeGear(n:BYTE); PROCEDURE Accelerator (n:REAL); …

Теперь предположим, что

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

СВОЙСТВА: - грузоподъемность (load: WORD); - кузов опущен/поднят (lift:BOOLEAN); - упоры опущены/подняты (legs: BOOLEAN).

МЕТОДЫ: - понять кузов (procedure LiftUp); - опустить кузов (procedure LiftDown); - понять упоры (procedure LegsUp); - опустить упоры (procedure LegsDown).

Все же остальные свойства и методы возьмем из типа Tvehicle. Для этого нужно создать объект-потомок:

TYPE Ttruck=CLASS(Tvehicle)

{ в скобках – объект-родитель Tvehicle } PRIVATE load: WORD; lift:BOOLEAN; legs: BOOLEAN; procedure LiftUp; procedure LiftDown; procedure LegsUp; procedure LegsDown; END;

Имя объекта-родителя указывается в скобках после слова CLASS. Теперь в объекте типа Ttruck существуют (унаследованы) все свойства и методы объекта Tvehicle, а также ряд новых методов, относящихся только к самосвалам.

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

10.1. Принцип полиморфизма

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

Например:

type TCar = Class

procedure Move;

end;

Ttruck = CLASS(TCar)

procedure Move;

end;

Здесь и у объекта-родителя Tcar, и у объекта-потомка Ttruck есть метод с названием Move. Внутренний код этих методов разный. Как же Паскалю определить, какой метод вызывать?

Очень просто – по типу переменной-объекта:

var Car: TCar;

truck: Ttruck;

begin

truck:=TTuck.Create;

Car:=TCar.Create;

{ вызовется метод Move класса Ttruck }

truck.Move;

{ вызовется метод Move класса Tcar }

Car.Move; . .

В данном примере есть два объекта: Car типа Tcar и truck типа Ttruck. При вызове метода Move объекта Car будет выполняться код, относящийся к объектному типу Tcar, а при вызове метода Move объекта Truck - относящийся к объектному типу Ttruck.

Зачем нужен полиморфизм? Прежде всего - для удобства программиста. Во всех сходных по смыслу объектах методы, выполняющие одни и те же операции (хотя и разными способами) называются одинаково.

А как быть, если нужно вызвать из объекта-потомка на выполнение родительский метод, а в объекте-потомке уже есть метод с таким именем? Такая задача возникает довольно часто. Рассмотрим метод "Начало движения" для легковой машины и самосвала. Очевидно, самосвалу сначала нужно опустить кузов, если он поднят, и поднять упоры. Далее же пуск легкового автомобиля и самосвала будут происходить одинаково. Было бы логично вынести эту одинаковую часть "вверх", в метод "Начало движения" объекта-родителя, а для самосвала в методе "Начало движения" сначала выполнить ряд дополнительных действий, а затем вызвать метод родителя – там уже написано все остальное.

Если у объекта есть родитель, можно вызывать его методы, совпадающие по названию с методами самого объекта, при помощи оператора INHERITED:

PROCEDURE Ttruck.Move; BEGIN { специфические для самосвала действия }

{вызывается метод родителя} INHERITED Move;

… END;