作者:巴哈姆特
(转载请注明出处并保持完整)
在对象化中,类的继承是一个非常强大的机制;而更加强大的继承机制应该是来自从一个接口的继承。
type IInterface
= interface [ '' ] function
QueryInterface( const IID: TGUID;
out Obj): HResult; stdcall; function
_AddRef: Integer ;
stdcall; function
_Release: Integer ;
stdcall; end ; |
我们可以看到,和类的基本声明差不多,只是由关键字class改成了interface。
type INewInterface
= interface (IInterface) //
定义一个新的接口INewInterface,并告诉编译器它是继承自IInterface接口 .... end ; |
这里要注意一点,就是我们说过,接口的TGUID是每一个接口的唯一标识,那么也就是说,TGUID是不能重复的。你不能简单的从别处抄袭过来,那 样是错误的。如果你需要一个TGUID,你可以在Delphi的代码编辑框中同时按下CTRL+SHIFT+G来获得一个新的TGUID值,这个值是 Delphi为你自动生成的。
type INewInterface
= interface ... end ; |
这里要注意一点,就是我们说过,接口的TGUID是每一个接口的唯一标识,那么也就是说,TGUID是不能重复的。你不能简单的从别处抄袭过来,那 样是错误的。如果你需要一个TGUID,你可以在Delphi的代码编辑框中同时按下CTRL+SHIFT+G来获得一个新的TGUID值,这个值是 Delphi为你自动生成的。
其实也是定义了一个继承自IInterface的新接口INewInterface(和类名前加一个大写字母T一样,我们习惯于在接口名前加一个大写字母I,当然这只是一个命名约定)
type TNewInterfaceClass
= class (TInterfacedObject,
INewInterface) //
TInterfacedObject为类名,INewInterface为我们上面定义的接口名 ... end ; |
一般,我们用来实现接口的基类不会选TObject而会选TInterfacedObject,理由是TInterfacedObject类已经帮我们实现了IInterface接口中的方法,我们只需要实现我们自己接口中新的方法就可以了。
var NewFace:
INewInterface; begin NewFace:=
TNewInterfaceClass . Create();
// 创建接口 NewFace . xxx;
// 调用接口中的方法 NewFace:=
nil ; // 释放 end ; |
有朋友可能会奇怪,接口的释放为什么只是直接赋为nil?我们前面说过了:接口即没有构造方法,也没有析构方法。既然没有析构方法,那么就意味着我们不能用释放类的方式来释放接口。
type TNewInterfaceClass
= class (TInterfacedObject, IInterface1,
IInterface2) ... end ; |
同样,实现多个接口的类必须依次实现每个接口中定义的方法。
type IInterface1
= interface (IInterface) //
接口1 fucntion
Func(): Boolean ; end ; IInterface2
= interface (IInterface) //
接口2 function
Func(): Boolean ; end ; TClasses
= class (TInterfacedObject, IInterface1,
IInterface2) public function
IInterface1 . Func:
Func1; function
IInterface2 . Func:
Func2; {
为同名方法起别名 } function
Func1: Boolean ; function
Func2: Boolean ; {
声明方法 } end ; |
Delphi中还可以使用imploements指示符用于委托另一个类或接口来实现接口的某个方法,有时这个方法又被称为委托实现,关于implements的用法如下:
type TInterClass
= class (TInterfacedObject,
IInterface1) ... function
GetClasses: TClasses; property
Face: TClasses read GetClasses implements
IInterface1; ... end ; |
上面的代码中,implements指示字会要求编译器在Face属性中寻找实现IInterface1接口的方法,属性的类型必须是一个类或一个接口。implements可以指定多个接口,彼此用逗号分隔。
INewInterface
= interface (IInterface) //
定义接口 function
SayHello: string ;
stdcall; //
接口方法 end ; TNewClass
= class (TInterfacedObject,
INewInterface) public function
SayHello: string ;
stdcall; //
第一个类实现接口中的方法 end ; TNewClass1
= class (TInterfacedObject,
INewInterface) private FNewClass:
INewInterface; public //
注意,在这个类中并没有实现接口中的SyaHello方法 constructor
Create; destructor
Destroy; override; property
NewClass: INewInterface read FNewClass implements INewInterface; //接口对象委托
如果是类对象委托应该是 //
property NewClass: TNewClass read FNewClass implements INewInterface; end ; implementation function
TNewClass . SayHello:
string ; begin Result:=
ClassName; ShowMessage(Result); end ; constructor
TNewClass1 . Create; begin inherited
Create(); FNewClass:=
TNewClass . Create; //
在构造方法中创建接口 end ; destructor
TNewClass1 . Destroy; begin FNewClass:=
nil ; //
在析构方法中释放接口 inherited
Destroy(); end ; |
调用的例子:
var NewInterface:
INewInterface; begin NewInterface:=
TNewClass1 . Create; NewInterface . SayHello; NewInterface:=
nil ; end ; |
题外话:如果你还没有接触过COM/COM+的话,也许你会认为接口十分麻烦(PS: 当年我刚学的时候真想一脚把发明接口机制的人踹死),但是接口经过COM的封装后,将变的非常的有意义,呵呵!