初探Object Pascal的类(十)

覆盖方法

先来讨论下虚拟方法,还是以TAirplane为例,注意到TakeOff方法在TAirplane类中是虚拟方法(TakeOff方法的声明的结尾有virtual关键字),TakeOff方法由SendMessage调用,并响应MsgTakeOff消息,如果它的派生类TMilitaryPlane类没有提供自己的TakeOff方法,基类TAirplaneTakeOff方法就会被调用。由于TMilitaryPlane类提供了一个TakeOff方法,这样就调用TMilitaryPlane类的TakeOff方法,而不调用基类的方法。

在派生类中代替一个基类的方法称作为覆盖方法

为了能够做覆盖工作,此方法的特征必须与基类中的方法严格匹配,也就是说,其返回类型、方法名和参数表都必须要与基类方法一致。另外,派生类中的方法必须用关键字override声明。

Note

Object Pascal也有一种动态方法,就大部分程序员来说,对待动态方法与对待虚拟方法是一样的。其不同之处在于虚拟方法指针存放在类的虚拟方法表(VMT,Virtual Method Table)中。

目前是否理解这种不同并不重要,这里只是让大家知道存在动态方法,以免在翻阅Delphi例子和VCL源代码时遇到它,在大部分情况下,在程序中处理动态方法与处理虚拟方法一样。

用覆盖方法代替基类方法,或者用覆盖方法来加强基类方法。以TakeOff方法为例,若想要完全代替TAirplane类提供的TakeOff方法,就可以覆盖它,下面提供了所需要的代码:

procedure TMilitaryPlane.TakeOff(Dir: Integer);
begin
  { 新代码}
end;

如果想要继承基类的功能,并还要在此基础上增加一些功能,就应该先调用基类方法,然后增加新代码。调用基类的方法用关键inherited,例如:

procedure TMilitaryPlane.TakeOff(Dir: Integer);
begin
  { 首先调用基类的TakeOff方法}
  inherited TakeOff(Dir);
  { 新代码}
end;

通过调用基类方法,可以得到写在基类中方法的原始性能,然后可在调用基类方法之前或之后增加新代码来加强基类方法。注意TakeOff方法声明在TAirplane类的protected段,若是在private段,它将不能工作,因为即使是派生类也不能存取其祖先类的私有成员,通过设置TakeOff方法为保护的(protected),从而把它从外界隐藏起来,但其派生类仍可以存取。

Note

对于私有存取(private)和保护存取(protected)规则有一个例外,如果派生类声明在基类的同一单元中,那么基类的私有字段和方法对派生类都是有效的,但若派生类声明在独立的单元中,那么只有基类的保护字段和方法对派生类是有效的。

当从另一个派生类时,必须确保调用基类的构造函数,这样才能使所有的祖先类作正确的初始化,调用基类构造函数也要用关键则inherited,在看看TAirplane类的构造函数:

constructor TAirplane.Create(AName: string; AKind: Integer);
begin
  { 初始化过程,设置飞机名称、类型和升限}
  inherited Create;
  Name := AName;
  Kind := AKind;
  Status := OnRamp;
  case Kind of
    Airliner: Ceiling := 35000;
    Commuter: Ceiling := 20000;
    PrivateCraft: Ceiling := 8000;
  end;
end;

注意调用基类的Create构造函数就是保证正确的创建此类。当声明类时,如果没有明确声明基类,那么其基类自动为TObject。在类构造函数中一定要调用基类构造函数。

posted on 2011-12-30 23:21  pchmonster  阅读(1691)  评论(0编辑  收藏  举报

导航