Delphi接口使用实例介绍
对于Object Pascal语言来说,最近一段时间最有意义的改进就是从Delphi3开始支持接口(interface),接口定义了能够与一个对象进行交互操作的一组过程和函数。对一个接口进行定义包含两个方面的内容,一方面是实现这个接口,另一方面是定义接口的客户。一个类能实现多个接口,即提供多个让客户用来控制对象的“表现方式”。
正如名字所表现的,一个接口就是对象和客户通信的接口。这个概念像C++中的PUREVIRTUAL类。实现接口的函数和过程是支持这个接口的类的工作。
在这里你将学到接口的语言元素,要想在应用程序中使用接口,请参考COM和ActiveX方面的资料;
1.定义接口
就像所有的Delphi类都派生于TObject一样,所有的接口都派生于一个被称为是IUnknown的接口,IUnknown在system单元中定义如下:
IDispatch = interface(IUnknown)
['{00020400-0000-0000-C000-000000000046}']
function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
function GetIDsOfNames(const IID: TGUID; Names: Pointer; NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
end;
正如你所看到的,接口的定义就像是类的定义,最根本的不同是在接口中有一个全局唯一标识符(GUID),它对于每一个接口来说是不同的。对IUnknown的定义来自于Microsoft的组件对象模型(COM)规范。
如果你知道怎样创建Delphi的类,那么定义一个定制的接口是一件简单的事情,下面的代码定义了一个新的接口称为IFoo,它包含一个被称为F1()的方法:
type
IFoo = Interface
['{2137BF60-AA33-11D0-A9BF-9A4537A42701}']
function F1 : Integer;
end;
提示在Delphi的IDE中,按Ctrl+Shift+G键可以为一个接口生成一个新的GUID。
下面的代码声明了一个称为IBar的接口,它是从IFoo接口继承来的:
type
IBar = Interface(IFoo)
['{2137BF61-AA33-11D0-A9BF-9A4537A42701}']
function F2 : Integer;
end;
2.实现接口
下面的代码演示了在一个类TFooBar中怎样实现IFoo和IBar接口:
type
TFooBar = class(TInterfacedObject, IFoo, IBar)
function F1 : Integer;
function F2 : Integer;
end;
function TFooBar.F1 : Interger;
begin
Result := 0;
end;
function TFooBar.F2 : Interger;
begin
Result := 0;
end;
注意,一个类可以实现多个接口,只要在声明这个类时依次列出要实现的接口。编译器通过名称来把接口中的方法与实现接口的类中的方法对应起来,如果一个类只是声明要实现某个接口,但并没有具体实现这个接口的方法,编译将出错。
如果一个类要实现多个接口,而这些接口中包含同名的方法,必须把同名的方法另取一个别名,请看下面的程序示例:
type
IFoo = Interface
['{2137BF60-AA33-11D0-A9BF-9A4537A42701}']
function F1 : Integer;
end;
type
IBar = Interface
['{2137BF61-AA33-11D0-A9BF-9A4537A42701}']
function F1 : Integer;
end;
TFooBar = class(TInterfacedObject, IFoo, IBar)
//为同名方法取别名
function IFoo.F1 = FooF1;
function IBar.F1 = BarF1;
//接口方法
function FooF1 : Integer;
function BarF1 : Integer;
end;
function TFooBar.FooF1 : Interger;
begin
Result := 0;
end;
function TFooBar.BarF1 : Interger;
begin
Result := 0;
end;
3.implements指示符
implements指示符是在Delphi4中引进的,它的作用是委托另一个类或接口来实现接口的某个方法,这个技术有时又被称为委托实现,关于implements指示符的用法,请看下面的代码:
type
TSomeClass = class(TInterfacedObject, IFoo)
//Stuff
function GetFoo : TFoo;
property Foo : TFoo read GetFoo implements GetFoo;
//Stuff
end;
在上面例子中的implements指示符是要求编译器在Foo属性中寻找实现IFoo接口方法。属性的类型必须是一个类,它包含IFoo方法或类型是IFoo的接口或IFoo派生接口。implements指示符后面可以列出几个接口,彼此用逗号隔开。
implements指示符在开发中提供了两个好处:首先,它允许以无冲突的方式进行接口聚合。聚合
(Aggregation)是COM中的概念。它的作用是把多个类合在一起共同完成一个任务。其次,它能够延后占用实现接口所需的资源,直到确实需要资源。例如,假设实现一个接口需要分配一个1MB的位图,但这个接口很少用到。因此,可能平时你不想实现这个接口,因为它太耗费资源了,用implements指示符后,可以只在属性被访问时才创建一个类来实现接口。
4.使用接口
当在应用程序中使用接口类型的变量时,要用到一些重要的语法规则。最需要记住的是,一个接口是生存期自管理类型的,这意味着,它通常被初始化为nil,它是引用计数的,当获得一个接口时自动增加一个引用计数;当它离开作用域或赋值为nil时它被自动释放。下面的代码演示了一个接口变量的生存期自管理机制。
var
I : ISomeInterface;
begin
//I被初始化为nil
I := FunctionReturningAnInterface; //I的引用计数加1
I.SomeFunc;
//I的引用计数减1,如果为0,则自动释放。
end;
关于接口变量的另一个规则是,一个接口变量与实现这个接口的类是赋值相容的,例如,下面的代码是合法的:
procedure Test(FB : TFooBar)
var
F : IFoo;
begin
F :=FB; //合法,因为FB支持IFoo
.
.
.
最后,类型强制转换运算符as可以把一个接口类型的变量强制类型转换为另一种接口。示例如下:
var
FB : TFooBar;
F : IFoo;
B : IBar;
begin
FB := TFooBar.create;
F :=FB; //合法,因为FB支持IFoo
B := F as IBar; //把F转换为IBar
另,参见:http://www.cnpack.org/showdetail.php?id=571&lang=zh-cn
Delphi接口使用实例介绍的更多相关文章
- 【转】Web Service单元测试工具实例介绍之SoapUI
转自:http://blog.csdn.net/oracle_microsoft/article/details/5689585 SoapUI 是当前比较简单实用的开源Web Service 测试工具 ...
- osg实例介绍
osg实例介绍 转自:http://blog.csdn.net/yungis/article/list/1 [原]osgmotionblur例子 该例子演示了运动模糊的效果.一下内容是转自网上的:原理 ...
- tcpdump wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 实例介绍
tcpdump wireshark 实用过滤表达式(针对ip.协议.端口.长度和内容) 实例介绍 标签: 网络tcpdst工具windowslinux 2012-05-15 18:12 3777人阅读 ...
- Web Service单元测试工具实例介绍之SoapUI
原文 Web Service单元测试工具实例介绍之SoapUI SoapUI是当前比较简单实用的开源Web Service测试工具,提供桌面应用程序和IDE插件程序两种使用方式.能够快速构建项目和组 ...
- delphi 接口Interface
学习 delphi 接口 一切都是纸老虎!!! 第四章 接口 前不久,有位搞软件的朋友给我出了个谜语.谜面是“相亲”,让我猜一软件术语.我大约想了一分钟,猜 出谜底是“面向对象”.我 ...
- Spring IOC(通过实例介绍,属性与构造方法注入)
概括说明:下面通过实例介绍下属性方法注入.构造方法注入 1.源码结构图 2.代码介绍 (1).Dao接口 :UserDAO (2).Dao接口实现:UserDAOImpl (3).实体类:User ( ...
- Delphi 接口使用中,对象生命周期管理,如何释放需要注意的问题
网上有篇文章<Delphi接口编程的两大陷阱>,里面提到接口的生存期管理的问题.但该文章里面提到的两个问题,其实都是对 Delphi 不理解导致的. 先说该篇文章中提到的第一个问题为什 ...
- delphi 接口
第四章 接口 前不久,有位搞软件的朋友给我出了个谜语.谜面是“相亲”,让我猜一软件术语.我大约想了一分钟,猜 出谜底是“面向对象”.我觉得挺有趣,灵机一动想了一个谜语回敬他.谜面是“ ...
- 多线程的基本概念和Delphi线程对象Tthread介绍
多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行 ...
随机推荐
- APM系列-国外新兴厂商New Relic vs. AppDynamics
前: New Relic的上市使得IT和资本界开始重新重视APM,当然跟传统APM相比,New Relic还是有相当的创新,另外还有一点是目前的创业潮导致的企业级需求增大. In recent yea ...
- ubuntu下安装apcu扩展
apcu前身是apc,apc分为系统缓存和用户缓存 1.系统缓存是指PHP执行时增加缓存,减少PHP文件的反复检查和编译,从而达到系统加速的目的. 2.用户缓存是指,PHP代码中将数据写入缓存,是用户 ...
- mysql use index() 优化查询
mysql use index() 优化查询 FORCE INDEX/IGNORE INDEX 的语法: SELECT *** FROM TABLE [{USE|IGNORE|FORCE} INDEX ...
- vue同胞组件通讯解决方案(以下为一种另外可用vuex解决)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 2019年今日头条机试_JAVA后台岗_第一题
广度优先遍历: import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; class Nod ...
- 7-Java-C(四平方和)
题目描述: 四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和. 如果把0包括进去,就正好可以表示为4个数的平方和. 比如: 5 = 0^2 + 0^2 + 1^2 + ...
- 在Eclipse中设置自动补全
在Eclipse中菜单中,Window->Preferences->Java->Editor->Content Assist中的Auto activation triggers ...
- QT +坐标系统 + 自定义控件 + 对象树的验证(自动进行析构)_内存回收机制
通过创建一个新的按钮类,来进行析构函数的验证,即对象树概念的验证.当程序结束的时候会自动的调用析构函数, 验证思路: 要验证按钮会不会自动的析构,(即在QPushButton类里面的析构函数添加qDe ...
- linux 安装nginx 集成emq
1:下载nginx-1.12.2.tar.gz http://nginx.org/en/download.html 2:解压 tar -zxvf nginx-1.12.2.tar.gz 3:进行co ...
- 第1节 flume:8、flume采集某个文件内容到hdfs上
2. 采集文件内容到HDFS 需求分析: 采集需求:比如业务系统使用log4j生成的日志,日志内容不断增加,需要把追加到日志文件中的数据实时采集到hdfs. 同一个日志文件的内容不断增 ...