欢迎来到天天文库
浏览记录
ID:22679875
大小:67.01 KB
页数:9页
时间:2018-10-30
《delphi接口的底层实现》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、Delphi接口的底层实现引言 接口是面向对象程序语言中一个很重要的元素,它被描述为一组服务的集合,对于客户端来说,我们关心的只是提供的服务,而不必关心服务是如何实现的;对于服务端的类来说,如果它想实现某种服务,实现与该服务相关的接口即可,它也不必与使用服务的客户端进行过多的交互。这种良好的设计方式已经受到很广泛的应用。 早在Delphi3的时候就引入了接口的概念,当时完全是因为COM的出现而诞生的,但经过这么多版本的进化,Delphi的接口已经成为ObjectPascal语言的一部分,我们完全可以用接口来完成我们的
2、设计,而不用考虑与COM相关的东西。 那么接口在Delphi中是如何实现的呢,很多人想得很复杂,其实它的本质不过也是一些简单的数据结构和调用规则。笔者假设读者已经有接口的使用经验,本文试图向你展示接口在Delphi中的实现过程,使你在使用接口的时候,知其然而知其所以然。 接口在内存中的分布 接口在概念上并不是一个实体,它需要与实现接口的类关联,如果脱离了这些类,接口就变得没有意义了。但接口在内存中仍然有其布局,它依附在对象的内存空间中。 Delphi对象本质上是一个指向特定内存空间的指针,这块内存的前四个字节是一
3、个指针指向类的VMT表,接下来排布对象的数据成员,如果对象实现了接口,则在后面又排着一系列指针,我们可以认为这些指针就是对应的接口,每个指针就指向一个接口方法表。我们来看一下简单的例子:type ITest1 = interface ['{5347BB0D-89B7-4674-A991-5C527BE6F8A8}'] procedure SayHello1; end; ITest2 = interface ['{567B86BB-711D-40C2-8E5E-364B742C2FF1}'] procedure
4、 SayHello2; end; TTest = class(TInterfacedObject, ITest1, ITest2) public procedure SayHello1; procedure SayHello2; end;... ...implementation{ TTest }procedure TTest.SayHello1;begin showMessage(IntToStr(FRefCount)); ShowMessage('Itest1 say hello');end;procedu
5、re TTest.SayHello2;begin ShowMessage(IntToStr(FRefCount)); ShowMessage('Itest2 say hello');end;end.上面是两个接口的声明以及一个实现接口的类,TTest类在内存中的分布可以用下图来表示:其中FRefCount为父类TInterfacedObject的一个成员,接下来存放的是TInterfacedObject实现的接口IInterface,再下来分别是TTest类实现的ITest2和ITest1指针。各个接口指针分别指向各自的方法表
6、,注意ITest2和ITest1是从IInterface继承下来的,所以自然就有了IInterface的所有方法。方法表中每个指针指向方法真正实现的地方,其实这个说法只是暂时的,稍后会解释方法表中的指针真正指向的地方,并说明其原因。 上面的内存分布并非笔者随意想出来的,而是经过多次测试证实的,下面我们用一些代码来证实上面分布图:var test:Itest2;begin test:=TTest.Create; test.SayHello2;end; 在证明接口的内存布局之前,需要了解接口的变量是个什么东西,比如上面的tes
7、t是什么,它的本质上是一个指针,在没有被赋值之前,它指向空;而得到对象的赋值之后,它指向上面分布图中的Itest2处,对于同一个对象的多个接口变量来说,它们的“值”不一定是相等的,比如有下面的代码:Var Test1:ITest1; Test2:ITest2; Test:TTest;Begin Test:=Ttest.Create; Test1:=Test; Test2:=Test; IfInteger(Test1)<>Integer(Test2)then ShowMessage('itisnoteqeual');End;最后
8、,会弹出一个对话框,说明Test1和Test2是不相等的;只有属性同一种接口类型,这两个变量才会相等,比如Test1和Test2都是Iinterface,则他们的“值”是相等的。 好了,回过头来看看之前的代码片段吧,在第4行设置断点,运行程序并使上
此文档下载收益归作者所有