Delphi的一些方法

1)Delphi 的函数覆盖(Override)与重载(overload)
  Delphi 用override 关键字来说明函数覆盖的。被覆盖的函数必须是 虚(virtual) 的,或者是 动态(dynamic) 的,也就是说该函数在 声明时 应该包含这两个指示字中的一个,比如:
procedure Draw; virtual;
在需要覆盖的时候,只需要在 子类中用override  指示字重新声明一下就可以了。

procedure Draw; override;


virtual 虚类型
dynamic 动态
overload 重载
override 重写

<<<<<<<<<<

1、静态方法是方法的缺省类型,对它就像对通常的过程和函数那样调用,编译器知道这些方法的地址,所以调用一个静态方法时它能把运行信息静态地链接进可执行文件,所以,静态方法速度最快,但它们却不能被覆盖来支持多态性。

2、虚拟方法和静态方法的调用方式相同。由于虚拟方法能被覆盖,在代码中调用一个指定的虚拟方法时编译器并不知道它的地址,因此,编译器通过建立虚拟方法表(VMT)来查找在运行时的函数地址。所有的虚拟方法在运行时通过VMT来高度,一个对象的VMT表中除了自己定义的虚拟方法外,还有它的祚的所有的虚拟方法,因此虚拟方法比动态方法用的内存要多,但它执行得比较快。

3、动态方法跟虚拟方法基本相似,只是它们的高度系统不同。编译器为每一个动态方法指定一个独一无二的数字,用这个数字和动态方法的地址构造一个动态方法表(DMT)。不像VMT表,在DMT表中仅有它声明的动态方法,并且这个方法需要祖先的DMT表来访问它蓁的动态方法。正因为这样动态方法比虚拟方法用的内存要少,但执行起来罗慢,因为有可能要到祚对象的DMT中查找动态法。

4、OP通过覆盖使一方法在不同的派生类间表现出不同的行为。OP中能被覆盖的方法是在声明时被标识为virtual或dynamic的方法。为了覆盖一个方法,在派生类的声明中用override代替virtual或dynamic。用了override后,编译器就会用新的方法替换VMT中原先的方法,而原先的方法也还存在,而如果用override再次声明一个静态方法,则是真正的覆盖,是用新的方法完全替换在祖先类中的同名方法。



>>>>>>>>>>


关于方法定义关键字的说明:
  在过程定义声明时包括了的关键字的含义:
static 表示是静态方法;静态方法是方法的缺省类型,不能被覆盖;
virtual 表示是虚拟方法;
dynamic 表示是动态方法;
  这两类方法的共同点是都可以被覆盖(override),区别仅在于运行时调用方法时的派发机制,virtual方法为执行速度做了优化,而dynamic方法则为代码大小做了优化;经常被覆盖的方法应该定义为virtual方法;  

message 表示是消息处理方法;在关键字message后面的值指明了这个方法要响应的消息;用消息处理方法来响应Windows的消息,这样就不用直接来调用它;
override 表示是覆盖方法;要求祖先类中必须有该方法的定义,并且参数的顺序和类型及返值的类型必须匹配;用于扩展祖先类中的该方法而不是取代它(如不调用祖先类中的该方
法则等同于取代);
overload 表示是重载方法;用于一个类中有许多同名的方法带着不同的参数表的情形;(属性的读写方法不能被重载);
abstract 表示是抽象方法;是没有实现的方法,并且必须是virtual或dynamic方法,即
在abstract前面必须有virtual或dynamic关键字,其实现部分在派生类中;如
      procedure DoSomething; virtual; abstract;
reintroduce表示是重新声明的方法;用于方法的名称与祖先类中的某个方法名称相同的情形;
5.)virtual 和 dynamic定义的虚函数,都是为了子类override用的,只不过它们的实现不一样。vitrual 占用的空间大点,但速度快些。dynamci正好相反.
程序如下:
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
  private
    procedure wmCopyData(var AMessage: TMessage); message WM_COPYDATA;
  protected
    procedure WndProc(var AMessage: TMessage); override;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.WndProc(var AMessage: TMessage);
begin
  ...
  ...
  inherited WndProc(AMessage);
end;
procedure TForm1.wmCopyData(var AMessage: TMessage);
var
  pdsData: PCopyDataStruct;
  sGot   : AnsiString;
begin
  inherited;
  pdsData := PCopyDataStruct(AMessage.lParam);
  sGot := StrPas(pdsData^.lpData);
  SendMessage(hPartner, wm_Response, Self.Handle, id_GotData);
end;
end.
在上面程序中各位朋友注意了
   过程wmCopyData(var AMessage: TMessage); message WM_COPYDATA;在声明中未加任何说明即意味着是替换其父类的方法,其父类wnCopyData已不存在。而过程WndProc(var AMessage: TMessage); override;在声明中加入了override超越的说明即意味着是扩展以前的方法也就是保留了父类的方法并在其基础上增加了某些功能
按照这样的理解,那么我例中的wmCopyData方法就应该是用现在的新wmCopyData替换掉父类的wmCopyData方法,而在本例中的wmCopyData的过程中又加入了一句inherited即继承又是何意,是否意味着新的wmCopyData方法并没有替换掉父类的wmCopyData方法
这是message关键字的功劳. 所以不需要加override也能调用原先的处理过程
(其实都是替换了,wndproc, message中的inherited相当于callwindowproc)


TClass1   =   class     
    procedure   func1;   virtual;//virtual;这个是做什么的   
  end;   
  TClass2   =   class(TClass1)   
    procedure   func1;   override;//override这个是做什么的   
  end;   
virtual   的作用就是允许Tclass1的子类也可以有fun1的过程定义.   
override   的作用就是告诉tclass1在子类(tclass2)中重新定义了fun1过程.   
具体运行的时候,   
  a:   tclass1   ;   
  b:   tclass2   ;     
  a.fun1   调用   tclass1的     fun1   
  b.fun1   调用   tclass2的     fun2     
1). virtual翻译过来就是虚方法,它自已可以实现也可以不实现,主要给后代一个可以override的方法。以便子类和父类用相同的函数下实现不同的功能。   
2). override就是子类用相同的函数名来做和父类不同的事,但不覆盖父类方法,(还可以继承父类的方法)函数名相同而不带override字样的函数不同。  


----------===============



     对象的方法能定义成静态(static)、虚拟(virtual)、动态(dynamic)或消息处理(message)。请看下面   
  的例子:   
    
          TFoo   =   class   
              procedure   IAmAStatic;   
              procedure   IAmAVirtual;   virtual;   
              procedure   IAmADynamic;   dynamic;   
              procedure   IAmAMessage(var   M:TMessage);   message   wm_SomeMessage;   
          end;   
            
      1.   静态方法   
          IAmAStatic   是一个静态方法,静态方法是方法的缺省类型,对它就像对通常的过程和函数那样调   
  用。编译器知道这些方法的地址,所以调用一个静态方法时它能把运行信息静态地链接进可执行文件。   
  静态方法执行的速度最快,但它们却不能被重写来支持多态性。   
    
      2.   虚拟方法   
          IAmAVirtual   是一个虚拟方法。虚拟方法和静态方法的调用方式相同。由于虚拟方法能被重写,在   
  代码中调用一个指定的虚拟方法时编译器并不知道它的地址。因此,编译器通过建立虚拟方法表(VMT)   
  来查找在运行时的函数地址。所有的虚拟方法在运行时通过VMT来调度,一个对象的VMT表中   
  除了自己定义的虚拟方法外,还有它的祖先的所有的虚拟方法,因此虚拟方法比动态方法用的内存要   
  多,但它执行得比较快。   
    
      3.   动态方法   
          IAmADynamic   是一个动态方法,动态方法跟虚拟方法基本相似,只是它们的调度系统不同。编译   
  器为每一个动态方法指定一个独一无二的数字,用这个数字和动态方法的地址构造一个动态方法表   
  (DMT)。不像VMT表,在DMT表中仅有它声明的动态方法,并且这个方法需要祖先的DMT表来访问   
  它其余的动态方法。正因为这样,动态方法比虚拟方法用的内存要少,但执行起来较慢,因为有可能   
  要到祖先对象的DMT中查找动态方法。   
    
      4.   消息处理方法   
          IAmAMessage   是一个消息处理方法,在关键字message后面的值指明了这个方法要响应的消息。   
  用消息处理方法来响应Windows的消息,这样就不用直接来调用它。   
    
      5.   方法的重写   
          在Object   Pascal重写一个方法用来实现OOP的多态性概念。通过重写使一方法在不同的派生类间   
  表现出不同的行为。Object   Pascal中能被重写的方法是在声明时被标识为virtual或dynamic的方法。为   
  了重写一个方法,在派生类的声明中用override代替virtual或dynamic。例如,能用下面的代码重写   
  IAmAVirtual和IAmADynamic方法:   
    
          TFooChild   =   class(TFoo)   
              procedure   IAmAVirtual;   override;   
              procedure   IAmADynamic;   override;   
              procedure   IAmAMessage(var   M:TMessage);   message   wm_SomeMessage;   
          end;   
    
  用了override关键字后,编译器就会用新的方法替换VMT中原先的方法。如果用virtual或dynamic替换   
  override重新声明IAmAVirtual和IAmADynamic,将是建立新的方法而不是对祖先的方法进行重写。同样,   
  在派生类中如果企图对一个静态方法进行重写,在新对象中的方法完全替换在祖先类中的同名方法。   
    
      6.   方法的重载   
          就像普通的过程和函数,方法也支持重载,使得一个类中有许多同名的方法带着不同的参数表,   
  能重载的方法必须用overload指示符标识出来,可以不对第一个方法用overload。下面的代码演示了一   
  个类中有三个重载的方法:   
    
          type   
              TSomeClass   =   class   
                  procedure   AMethod(I:Integer);   overload;   
                  procedure   AMethod(I:String);   overload;   
                  procedure   AMethod(I:Double);   overload;   
              end;   
    
      7.   重新引入方法名称   
          有时候,需要在派生类中增加一个方法,而这个方法的名称与祖先类中的某个方法名称相同。在   
  这种情况下,没必要覆盖这个方法,只要在派生类中重新声明这个方法。但在编译时,编译器就会发   
  出一个警告,告诉你派生类的方法将隐藏祖先类的同名方法。要解决这个问题,可以在派生类中使用   
  reintroduce指示符,下面的代码演示了reintroduce指示符的正确用法:   
          type   
              TSomeBase   =   class   
                  procedure   Cooper;   
              end;   
              TSomeClass   =   class(TSomeBase)   
                  procedure   Cooper;   reintroduce;   
              end;   
                
      8.   Self   
          在所有对象的方法中都有一个隐含变量称为Self,Self是用来调用方法的指向类实例的指针。Self   

  由编译器作为一个隐含参数传递给方法。  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值