Delphi 系统[24]关键字和保留字 virtual、dynamic、abstract、inline、static - 类方法类型


Delphi 系统[24]关键字和保留字  virtual、dynamic、abstract、inline、static - 类方法类型

1、定义:

  • virtual :虚拟方法可以被子类覆写(覆盖),虚拟方法可以加快调用速度,但浪费内存。
  • dynamic :动态方法可以被子类覆写,动态方法可以节省内存,但调用速度没有虚拟方法快。
  • abstract :抽象方法可以被子类覆写,abstract 关键字必须与 virtual 或dynamic 关键字同时使用。包含“抽象方法”的类称为“抽象类”。抽象类可以被实例化,但实例化的对象不能调用抽象方法,否则会抛出异常。
  • inline :定义内联函数或内联汇编代码,内联函数类似于宏,编译器在编译程序时,会将内联函数的代码直接搬到调用者的代码里面去,作为调用者的一部分,也就不存在调用内联函数的说法了,直接就是一行行代码。内联函数一般是体积较小且被频繁调用的函数。内联函数可以提高代码的执行效率。如果没有定义内联函数,则编译器会自己判断将那些函数作为内联函数处理,以便提高程序的执行效率,所以一般情况下我们不需要手动指定内联函数。内联说明对于编译器来说只是一种建议,编译器可以忽略这个建议,如果我们指定了内联函数而编译器觉得不合适,那么编译器可以拒绝将指定的函数内联。内联函数不是纯粹的函数,因此不能递归调用。

2、示例:

{ 虚拟方法 }
TObject = class
public
  procedure Dispatch(var Message); virtual;
  destructor Destroy; virtual;
end;

---------------------------------------------------------------------------------------
{ 动态方法 }
TCustomForm = class
protected
  procedure DoHide; dynamic;
  procedure DoShow; dynamic;
end;

---------------------------------------------------------------------------------------
{ TStrings 中的抽象方法 }
TStrings = class
protected
  function Get(Index: Integer): string; virtual; abstract;{ 这里只需要定义,具体功能靠子类去实现 }
  function GetCount: Integer; virtual; abstract; { 这里只需要定义,具体功能靠子类去实现 }
end;

--------------------------------------------------------------------------------------
{ 内联函数 inline}
function Test(S: string): string; inline;
begin
  Result := '显示结果:' + S;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Caption := Test(Caption);
  { 此处调用了内联函数,所以,在编译时,此处的代码就被改成了 Caption := '显示结果:' + Caption; 直接将内联函数的代码搬过来进行编译 }
end;

3、关于 virtual 和 dynamic 方法的一些说明:

要使方法虚拟或动态,请在其声明中包含virtual或dynamic指令。与静态方法不同,虚拟方法和动态方法可以在子类中重写。调用重写的方法时,方法调用中使用的类或对象的实际(运行时)类型(而不是声明的变量类型)决定要激活的实现。

要重写方法,请使用override指令重新声明它。重写声明必须在其参数的顺序和类型以及结果类型(如果有)上与祖先声明匹配。

在以下示例中,TFigure中声明的Draw方法在两个子类中被重写:

type
  TFigure = class
    procedure Draw; virtual;
  end;
  TRectangle = class(TFigure)
    procedure Draw; override;
  end;
  TEllipse = class(TFigure)
    procedure Draw; override;
  end;

给定这些声明,下面的代码说明了通过实际类型在运行时发生变化的变量调用虚拟方法的效果。

var
  Figure: TFigure;
begin
  Figure := TRectangle.Create;
  Figure.Draw;  // calls TRectangle.Draw
  Figure.Destroy;
  Figure := TEllipse.Create;
  Figure.Draw;  // calls TEllipse.Draw
  Figure.Destroy;
end; 

只能重写虚拟方法和动态方法。但是,所有方法都可以重载;请参阅重载方法。

虚拟与动态:

  • 虚拟方法和动态方法在语义上是等价的。它们只是在运行时方法调用调度的实现上有所不同。虚拟方法优化速度,而动态方法优化代码大小。
  • 一般来说,虚拟方法是实现多态行为最有效的方法。当基类声明许多可重写的方法,这些方法由应用程序中的许多子类继承,但只是偶尔被重写时,动态方法非常有用。

注:只有在有明显的、可观察到的好处时才使用动态方法。通常,使用虚拟方法。  

4、其他,请参考:

  

创建时间:2021.08.16  更新时间:

相关