//Ex1
Type
TFigure = class
procedure Draw;//*
end;
TRectangle = class(TFigure)
procedure Draw;//#
end;
var
Figure:TFigure;
Rectangle:TRectangle;
begin
Figure := TFigure.create;
Figure.Draw;//call TFigure.Draw;
Figure.Destroy;
Figure := TRectangle.create;
Figure.Draw;//** call TFigure.Draw;
Figure.Destroy;
TRectangle(Figure).Draw;//call TRectangle.Draw;
Figure.Destroy;
Rectangle := TRectangle.create;
Rectangle.Draw;//call TRectangle.Draw;
Rectangle.Destroy;
end;
//Ex2
/**
*Another Definition then what will happen if the following codes excute;
Type
TFigure = class
procedure Draw;virtual;
end;
TRectangle = class(TFigure)
procedure Draw;override;
end;
var
Figure:TFigure;
Rectangle:TRectangle;
begin
Figure := TFigure.create;
Figure.Draw;//call TFigure.Draw;
Figure.Destroy;
Figure := TRectangle.create;
Figure.Draw;//call TRectangle.Draw;
Figure.Destroy;
TRectangle(Figure).Draw;//call TRectangle.Draw;
Figure.Destroy;
Rectangle := TRectangle.create;
Rectangle.Draw;//call TRectangle.Draw;
Rectangle.Destroy;
end;
*/
在方法声明的时候,如果它和继承的方法有相同的名字,但不包含override限定符(Ex1),则该方法只是隐藏了继承下来的方法,并没有覆盖它。这两个方法在派生类中都存在,方法名是静态绑定的。所以可以看到,**行调用的是父类的draw,因为发生静态绑定。这是两段程序唯一不同的地方。
在Ex1中,*号行如果加上virtual,而#号行不变,也是属于方法被隐藏的例子。
关于reintroduce
在Ex1中,这是个隐藏父类方法的例子,TRectangle中的Draw隐藏了从TFigure中继承的Draw,编译器会给个警告,告诉你派生类的方法将隐藏父类的同名方法。要避免这个警告,在派生类的定义中引入reintroduce,改为:procedure Draw;reintroduce;
在下面这个例子中
type
T1 = class(Object)
procedure Act;virtual;
end;
T2 = class(T1)
procedure Act;reintroduce;
end;
在上面的例子中,满足上文中的叙述“在方法声明的时候,如果它和继承的方法有相同的名字,但不包含override限定符”,所以T2的Act隐藏了T1的Act,为了避免警告的出现用了reintroduce。
隐藏跟虚方法重载的一个联系:
type
T1 = class(Object)
procedure Act(I:Integer);overload;virtual;
end;
T2 = class(T1)
procedure Act(S:String);reintroduce;overload;
end;
可见,虚方法可以重载,并且重载时为了避免警告使用了reintroduce。