重载,覆盖,多态

一、override  重载

type

  TFigure = class

    procedure Draw; virtual;//(我的理解是)父类中可以使用父类的,子类中使用子类的。与“四”是有区别的。

  end;

  TRectangle = class(TFigure)

    procedure Draw; override;//a1

  end;

  TEllipse = class(TFigure)

    procedure Draw; override;//a2

  end;

使用

var

  Figure: TFigure;

begin

  Figure := TRectangle.Create;

  Figure.Draw;  // 执行a1

  Figure.Destroy;

  Figure := TEllipse.Create;

  Figure.Draw;  // 执行a2

end;

 

二、overload 多态

  procedure foo(i: integer); overload;

  procedure foo(d: double);  overload;

  procedure foo(v: variant); overload;

典型用法。如果是对于继承的。必须使用reintroduce

type

  T1 = class(TObject)

    procedure Test(I: Integer); overload; virtual;

  end;

  T2 = class(T1)

    procedure Test(S: string); reintroduce; overload;

  end;

   ...

  SomeObject := T2.Create;

  SomeObject.Test('Hello!');  // T2.Test

  SomeObject.Test(7);         // T1.Test

 

三、override & inherited

override是用来重载父类的procedure,

如果父类是virtual 或者 dynamic 方法的,就可以使用inherited,来调用父类中的代码。

 

四、abstract

procedure DoSomething; virtual; abstract;//如果是这个样式的,表示要在子类中实现(代码)。而父类中,其他procedure function可以使用这个procedure。

(这里的virtual似乎不能被dynamic替换)。

使用procedure DoSomething; virtual; abstract;和procedure DoSomething; virtual;的区别就是,前者的实现代码在子类,而后者实现代码在自身。后者可以在子类中override一下,使其子类也有自己的实现代码。

2009-4-11

在最近的代码中发现(不知道是不是D7的缘故)

procedure DoSomething; virtual; abstract;

procedure DoSomething; dynamic; abstract;

都是可以的。

而且在继承类中也可以不写实现代码。

在基类中如果要判断有没有被继承类写实现代码的方式不是

if Assigned(DoSomething) then ...

而是

if MethodAddress('DoSomething')<>nil then...

 

五、reintroduce

覆盖父类中的virtual 方式的内容。(编译器不会提示“xxx 被hide了”)

 

六、static

默认就是这个。

我们常打 procedure test(xx:Integer);其实就是static的。

这个比较好理解。

如果子类中,声明了一个test,跟父类无关。各自用各自的。

除非使用强制转换。比如:

type

  TFigure = class

    procedure Draw;

  end;

  TRectangle = class(TFigure)

    procedure Draw;

  end;

//实现

var

  Figure: TFigure;

  Rectangle: TRectangle;

begin

  Figure := TFigure.Create;

  Figure.Draw;  // 父类用父类的 TFigure.Draw

  Figure.Destroy;

  Figure := TRectangle.Create;

  Figure.Draw;  // 虽然初始化为子类,但是由于申明的是父类,所以Figure还是调用了父类的Draw  TFigure.Draw

  TRectangle(Figure).Draw;  // 强制转换成子类,就可以用TRectangle.Draw

  Figure.Destroy;

  Rectangle := TRectangle.Create;

  Rectangle.Draw;  // 子类用子类的 TRectangle.Draw

  Rectangle.Destroy;

end;

 

七、forward declaration提前定义。

用于类被提前使用。注意fd的class后面要立即加“;”不能使用括号和基类。

type

  TFigure = class;  // forward declaration

  TDrawing = class

    Figure: TFigure;

     ...

  end;

  TFigure = class  // defining declaration

    Drawing: TDrawing;

     ...

  end;

 

八、virtualdynamic

虚拟方法占用的内存大,调用速度快;动态方法相反。

如今,哪有PC内存不够的。

所以,笔者建议,就使用virtual吧。

2009-04-07

我知道了,内存是有不够用的时候。

所以这里修改说法,需要来回调用的用virtual,一般只用到1,2次的用dynamic。

像笔者一般写一个基类函数,只用一次,所以大部分都改成dynamic了。

但是有个地方必须要用virtual

private

  FItem:Integer

  procedure SetItem(Value:Integer);virtual;//dynamic不允许

public

  property Item:Integer;read FItem write SetItem;

end;
View Code

你可能感兴趣的:(多态)