Наследование – это механизм, позволяющий создавать иерархии объектов. При этом свойства объектов, расположенных на более высоких уровнях иерархии, автоматически относятся ко всем порожденным от них объектам.
Пусть необходимо создать программу, работающую не только с объектом-точкой, но еще и с объектом-окружностью. Очевидно, что объектный тип-окружность (назовем его circl) имеет много общего с существующим типом dot. Как и точка, окружность характеризуется парой координат x и y, определяющих положение центра окружности. Однако для создаваемого объекта-окружности необходимо добавить еще одно поле – радиус.
Что касается методов, то для нового типа circl подошел бы метод move, т.к. перемещение по экрану и точки, и окружности (перемещается, собственно, ее центр) осуществляется одинаково. Однако методы инициализации (Init), прорисовки (show) и сокрытия (hide) окружности придется описывать заново.
Свойство объектных типов – наследование – позволяет создать новый тип на основе уже существующего. При этом существующий тип, который служит основой для создания нового объекта, называют предком, или родительским типом, а создаваемый объект – потомком, или дочерним типом. Потомок автоматически наследует все поля и методы своего предка.
Следует заметить, что на основе существующего объекта можно создать любое количество потомков, причем глубина иерархии наследования ничем не ограничивается. При этом каждый объект-потомок может иметь единственного предка.
При описании типа-потомка должно указываться имя типа-предка, заключенное в круглые скобки.
type
circl= object (dot)
r:integer;
procedure Init(a,b,rad: integer);
procedure show;
procedure hide;
end;
В приведенном описании типа circl имеется поле r, определяющее радиус окружности, которого не было в типе dot. Кроме того, тип circl унаследовал все поля, которые присутствовали в родительском типе dot (два поля типа integer, определяющие координаты точки на экране), а также метод move, ко-торый в описании данного типа отсутствует.
Вместе с тем, действия по инициализации, отображению на экране и сокрытию окружности отличны от подобных действий в отношении точки. Поэтому методы, выполняющие названные действия, должны быть заново описаны (как при описании типа, так и при определении самих подпрограмм).
procedure circl.Init;
begin
x:=a;
y:=b;
r:= rad;
end;
procedure circl.show;
begin
setcolor(yellow);
circle(x,y,r);
end;
procedure circl.hide;
begin
setcolor(black);
circle(x,y,r);
end;
Как видим, методы потомка имеют те же имена, что и методы предка, однако описывают разные действия для разных объектов, т.е. методы объекта-потомка заменяют собой (или переопределяют) одноименные методы ро-дительского объекта.
Ниже приведен текст программы, в которой по сравнению с предыдущей программой добавлен объект cirсl (b соответственно объявлена переменная (создан экземпляр) obj2 объектного типа circl) и показаны переопределенные методы данного объекта – Init, show, hide.
program ex_obj2;
uses crt,graph;
type dot = object
x,y: integer;
procedure Init(a,b: integer);
procedure show;
procedure hide;
procedure move(Dx,Dy:integer);
end;
circl= object (dot)
r:integer;
procedure Init(a,b,rad: integer);
procedure show;
procedure hide;
end;
procedure dot.Init(a,b:integer);
begin
x:=a;
y:=b;
end;
procedure circl.Init;
begin
x:=a;
y:=b;
r:=rad;
end;
procedure dot.show;
begin PutPixel(x,y,white); end;
procedure circl.show;
begin setcolor(yellow); circle(x,y,r); end;
procedure dot.Hide;
begin PutPixel(x,y,black); end;
procedure circl.hide;
begin setcolor(black); circle(x,y,r); end;
procedure Dot.move;
begin
hide;
x:=x+Dx; y:=y+Dy;
show;
end;
Var i,j,err:integer;
c:char;
dot1:dot;
obj2:circl;
begin
i:=detect;
InitGraph(i,j,'');
err:=GraphResult;
if err<>0 then
writeln(graphErrorMsg(err))
else
begin
setcolor(yellow);
OutTextXY(getMaxX div 3,GetMaxY-30,'press 1 for draw pixel, 2 for draw cirlce');
c:=readkey;
case c of
{1} #49: begin
dot1.init(100,100);
dot1.show;
repeat
c:=readkey;
if c=#0 then
begin
c:=readkey;
with dot1 do
case c of
#72: move(0,-5);
#80: move(0,5);
#77: move(5,0);
#75: move(-5,0);
end
end;
until (c=#27) or (c=#13);
end;
{2} #50: begin
obj2.init(100,100,30);
obj2.show;
readkey;
obj2.hide;
readkey;
end;
end;
end;
end.
Как можно заметить, в приведенном выше примере для окружности (экземпляр obj2) не используется метод move, унаследованный от типа-предка dot. Чтобы разобраться в причинах такого «упущения», вернемся к методу move.
Вот его описание:
procedure Dot.move;
begin
hide;
x:=x+Dx; y:=y+Dy;
show;
end;
|