标签:
方法是属于一个给定对象的过程和函数,方法反映的是对象的行为而不是数据,前一篇提到的对象的两个重要的方法:构造方法和析构方法。
为了使对象能执行各种功能,你能在对象中定制方法
创建一个方法用两个步骤,首先在对象类型的声明中声明这个方法。然后再用代码定义方法。下面的代码就演示了声明和定义一个方法的步骤
type TBoogieNights = class Dance: Boolean; Procedure DoTheHustle; end; procedure TBoogieNights.DoTheHustle; begin Dance:= True; end;
注意:在定义方法体时,必须使用完整的名字,就像在定义方法DoTheHustle时那样。同时也要注意到,这个方法中,对象的Dance域能够被直接访问
一、方法的类型
对象的方法能定义成静态(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消息,这样就不用直接来调用它。
二、方法的覆盖
在Delphi覆盖一个方法用来实现OOP的堕胎性概念。通过覆盖使一种方法在不同的派生类间表现出不同的行为。Delphi中能被覆盖的方法是在声明时被标识为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,将是建立新的方法而不是对祖先的方法进行覆盖。
同样,在派生类中如果企图对一个静态方法进行覆盖,在新对象中的方法完全替换在祖先类中的同名方法。
三、方法的重载
就像普通的过程和函数,方法也支持重载,使得一个类中有许多同名的方法呆着不同的参数表,能重载的方法必须使用overload指示符标识出来,可以不对第一个方法用overload,下面的代码演示一个类中有三个重载的方法:
type TSomeClass = class procedure AMethod(I: Integer); overload; procedure AMethod(S: String); overload; procedure AMethod(D: Double); overload; end;
四、重新引入方法名称
有时候,需要在派生类中增加一个方法,而这个方法的名称与祖先类中的某个方法名称相同。在这种情况下,没必要覆盖这个方法,只要在派生类中重新声明这个方法。但是编译时,编译器就会发出一个警告,告诉你派生类的方法将隐藏祖先类的同名方法。要解决这个问题,可以在派生类中使用reintroduce指示符,下面的代码演示了reintroduce指示符的正确用法
type TSomeBase = class procedure Cooper; end; TSomeClass = class(TSomeBase) procedure Cooper; reintroduce; end;
五、Self
在所有对象的方法中都有一个隐含变量称为Self,Self是用来调用方法的指向类实例的指针。
Self由编译器作为一个隐含参数传递给方法
标签:
原文地址:http://www.cnblogs.com/xumenger/p/4434251.html