改变自己
我可以改变世界 改变自己

 

虚拟方法

虚拟方法在Delphi中利用关键字virtual定义。一个方法被声明为虚拟方法后,在调用时,程序需要动态地确定需要调用的方法。

现在重新定义上面的方法。需要注意的是此处使用了关键字override,表示方法的重载。代码如下所示:

type

TFigure = class

procedure Draw; virtual;

procedure Destroy

end;

procedure Tfigure.Draw;

begin

writeln('现在调用的是TFigure对象');

end;

type

TRectangle = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TRectAngle.Draw;

begin

writeln('现在调用的是TRectangle对象');

end;

type

TEllipse = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TEllipse.Draw;

begin

writeln('现在调用的是TEllipse对象');

end;

下面的代码调用上述图形对象的Draw方法:

var

Figure: TFigure;

begin

Figure := TRectangle.Create;

Figure.Draw; // 调用TRectangle.Draw

Figure.Destroy;

Figure := TEllipse.Create;

Figure.Draw; // 调用TEllipse.Draw

Figure.Destroy;

end;

上述代码中,第一次调用Figure.Draw时,当前对象是TRectangle类型;第二次调用Figure.Draw时,当前对象是TEllipse类型。

输出如下:

现在调用的是TRectangle对象

现在调用的是TEllipse对象

动态方法

动态方法利用dynamic关键字实现,它的功能与虚拟方法基本类似,不同主要体现在内部实现。与对象虚拟方法创建入口不同的是,dynamic给方法赋了一个数字,并存储相应代码的地址。动态方法列表只包含新加的和覆盖的方法入口,继承的动态方法的匹配是通过查找每一个祖先的动态方法列表(按与继承“反转的顺序”)来实现,因此动态方法用于处理消息(包括Windows消息)。实际上,消息处理过程的匹配方式与动态方法相同,只是定义方法不同。

动态方法没有对象VMT(Virtal Method Table,虚拟方法表)的入口,它们减少了对象消耗的内存数量。匹配动态方法比匹配一般的虚拟方法慢。因此,如果方法调用很频繁,最好将其定义为虚拟方法。

抽象方法

抽象方法利用关键字abstract实现,如果一个方法定义为抽象,则这个方法不需要在本类中实现。而在它的子类中,可以在重载方法中实现相关功能。

在下面代码中,TFigure对象的Draw方法声明为抽象,所以不需要实现TFigure.Draw方法,在它的子类中,子类数据根据各自不同的需求重载并实现这个方法。

type

TFigure = class

procedure Draw; virtual;abstract;

procedure Destroy

end;

type

TRectangle = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TRectangle.Draw;

begin

writeln('现在调用的是TRectangle对象');

end;

type

TEllipse = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TEllipse.Draw;

begin

writeln('现在调用的是TEllipse对象');

end;

如果一个类的抽象方法没有被重载,则这个方法是不能被调用的,否则会产生调用抽象方法的内部Delphi错误。

 方法重载

 

前面已经指出,通过override(方法重载)可以实现多态。方法重载即指多个方法可以享有相同的名字。通过在后代对象中声明一个与祖先对象重名的方法,就可以重载一个方法。如果想使这个方法在后代对象中做和祖先对象一样的工作,但是使用不同的方式,就可以重载这个方法。

如下几种情况将导致重载失败:

(1)祖先类中没有要重载的方法。

(2)要重载的方法在祖先类中被声明为静态方法。

(3)要重载的方法的参数类型或个数与祖先类中不同。

 方法继承

 

Delphi利用关键字inherited实现方法之间的互相继承。

如果inherited关键字后面没有方法名,那么当前方法就继承祖先类中与它同名的方法;如果inherited关键字后面有方法名,则当前方法就继承祖先类中指定的方法。

方法继承经常用在构造方法中,以便子类能够实现祖先类中的一些默认设置。

 构造方法

 

构造方法是一种特殊的方法,它为新对象分配内存并且指向这个新的对象。Delphi中的每个类都有构造方法,用来初始化该类的一个新的对象。

构造函数利用关键字constructor来声明,而构造函数的函数名可以任意选择,但是Delphi中函数名一般采用Create。构造函数可以用多个,但是Delphi建议每个对象只定义一个构造函数。

Delphi在构造函数内部实现的处理过程包括:

(1)首先在内存中开辟一块区域用于存储对象。

(2)然后对这块区域默认初始化设置。初始化,包括有序类型的字段清零,指针类型和类类型的字段设置为Nil,字符串类型的字段清为空等。

(3)执行构造中用户指定的动作。

(4)返回一个新分配的并初始化了的类类型实例。返回值的类型必须就是类的类型。

建立一个对象的实例,需要先调用Create方法,然后构造函数把这个实例赋给一个变量。构造方法不返回任何数据类型,在构造方法的实现中,也可以进行方法重载,如下例所示:

type

TShape = class(TGraphicControl)

private

FPen: TPen;

FBrush: TBrush;

procedure PenChanged(Sender: TObject);

procedure BrushChanged(Sender: TObject);

public

constructor Create(Owner: TComponent); override;

destructor Destroy; override;

...

end;

M

constructor TShape.Create(Owner: TComponent);

begin

inherited Create(Owner); // Initialize inherited parts

Width := 65; // Change inherited properties

Height := 65;

FPen := TPen.Create; // Initialize new fields

FPen.OnChange := PenChanged;

FBrush := TBrush.Create;

FBrush.OnChange := BrushChanged;

end;

上述例子中,TShape 类重载了TGraphicControl的构造函数。在构造函数内部,TShape类首先继承TGraphicControl的默认构造函数,实现一些常规设置,然后通过设置自己的一些特殊参数,实现自己的参数初始化,同时使自己与祖先类有所区别。


又一构造函数实例

delphi的构造函数的定义是:
constructor create;
delphi的析构函数的定义是:
destructor destroy;
析构函数是不能重载的,但是构造函数是可以重载的。
构造函数在重载的时候要在后面加“overload”,例如:
constructor create;overload;
constructor create(i:integer);overload;
注意,只有两个构造函数以上才叫重载,只有一个就不用“overload;”了。
默认的构造函数是:constructor create; 如果有重载的话,那么默认的构造函数后面也要加overload,正象上面的例子一样。
delphi构造函数在类外定义在什么位置呢?在implementation的后面。下面给出一个实例,可以从这个实例中看出构造函数的定义:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)   
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyForm1 = class(TForm1)    //自定义一个TMyForm1类
  public
    constructor Create; overload;  //构造函数有重载
    constructor Create(I: Integer); overload; //重载一个构造函数
  end;


var
  Form1: TForm1;

implementation

{$R *.dfm}
constructor TMyForm1.Create;   //这里定义构造函数
begin
  inherited Create(nil);  //inherited 表示调用父类的构造函数
end;
constructor TMyForm1.Create(I: Integer);
begin
  inherited Create(nil);
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  A: TMyForm1;
begin
  A := TMyForm1.Create(1);
  A.Show;
end;

end.

 

 

posted on 2008-11-28 19:31  dashan  阅读(511)  评论(0编辑  收藏  举报