Delphi 提示在Delphi的IDE中,按Ctrl+Shift+G键可以为一个接口生成一个新的GUID。
对于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
IFoo = 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
Delphi 提示在Delphi的IDE中,按Ctrl+Shift+G键可以为一个接口生成一个新的GUID。的更多相关文章
- 正则中关于修饰符g以及exec和match区别的一个小demo
代码: 输出结果 补充: reg.lastIndex:下一次正则捕获的开始查找的索引位置 ->正则的懒惰性就是因为默认情况下lastIndex值都是0,我们不管执行几次exec,都是从字符串的开 ...
- sublime 设置像IDE一样的 ctrl+鼠标左键 跳转到定义方法
鼠标点击菜单栏的Preferences,选择Browse Packages ,进入文件加之后,选择User 点击进入User,在User里面添加文件名为 Default (Windows).subli ...
- pycharm中全局搜索ctrl+shift+F快捷键无反应原因和解决
全局搜索快捷键无反应原因:搜狗输入法占用的ctrl+shift+F快捷键,简繁切换的快捷键.在搜狗输入法中将此项取消.
- delphi Ctrl+鼠标左键或者Find Declaration不能定位到源文件
在Delphi代码编辑器中使用Ctrl+鼠标左键可跳转到鼠标下的类所在的定义处,但今天发现一个奇怪的问题,EhLib组件的类无法跳转(包括uses中的pas文件),重新安装也是如此,后来经过验证,发现 ...
- 在IDE中添加widfly依赖
动机:在IDE中添加widfly依赖 原由:widfly实现了servlet接口,有我们对外交互时所需求的jar包 步骤: 第一步: 找到module依赖的地方 第二步:点击左侧的添加按钮,点击Lib ...
- 【转】Android开发中让你省时省力的方法、类、接口
转载 http://www.toutiao.com/i6362292864885457410/?tt_from=mobile_qq&utm_campaign=client_share& ...
- VS2005、VS2008中的快捷键、组合键大全
Ctrl+E,D ----格式化全部代码 Ctrl+E,F ----格式化选中的代码 CTRL + SHIFT + B生成解决方案 CTRL + F7 生成编译 CTRL + O 打开文件 CTRL ...
- java面试一日一题:mysql中的自增主键
问题:请讲下mysql中的自增主键 分析:该问题主要考察对mysql中自增主键的掌握,使用场景及如何设置 回答要点: 主要从以下几点去考虑 1.什么自增主键 2.使用场景是什么: 3.innodb_a ...
- Delphi应用程序的调试(十)调试器选项(在IDE中不要使用异常)
可在两个级别上设置调试选项:工程级和环境级.在前面的讲解中讲解了工程级调试选项,通过主菜单[Project | Options…]打开如下对话框: 可在Debugger Options对话框中设置全局 ...
随机推荐
- 278. First Bad Version
题目: You are a product manager and currently leading a team to develop a new product. Unfortunately, ...
- MyEclipse6.6 汉化过程
...
- linux下jdk安装 failed /usr/local/jdk1.6.0_10/jre/lib/i386/client/libjvm.so
今天在fedora core 4下面安装jdk1.6后,运行java -version,没有出现相关的版本信息,而是出现了以下错误: dl failure on line 685Error: fail ...
- 如何写计算机会议的rebuttal
其实最好的教材就是实例,恰好NIPS会议会把往年所有论文的Rebuttal都贴出来...,见这里:http://papers.nips.cc/ 同时,圈内同行也总结了不少经验,下面转帖其他人的经验 = ...
- USACO Section 2.3: Zero Sum
这题我做得比较麻烦,网上有个比较简单的程序. /* ID: yingzho1 LANG: C++ TASK: zerosum */ #include <iostream> #include ...
- c# ffmpeg常用参数
c# ffmpeg常用参数 转换文件格式的同时抓缩微图: ffmpeg -i "test.avi" -y -f image2 -ss 8 -t 0.001 -s 350x240 ...
- 《Linux内核设计与实现》读书笔记 - 目录 (完结)【转】
转自:http://www.cnblogs.com/wang_yb/p/3514730.html 读完这本书回过头才发现, 第一篇笔记居然是 2012年8月发的, 将近一年半的时间才看完这本书(汗!! ...
- YTU 2616: A代码完善--简易二元运算
2616: A代码完善--简易二元运算 时间限制: 1 Sec 内存限制: 128 MB 提交: 280 解决: 187 题目描述 注:本题只需要提交填写部分的代码,请按照C++方式提交. 编写二 ...
- oracle数据库导入导出命令!
Oracle数据导入导出imp/exp 功能:Oracle数据导入导出imp/exp就相当与oracle数据还原与备份. 大多情况都可以用Oracle数据导入导出完成数据的备份和还原(不会造成数据的丢 ...
- 使用Less color函数创建专业网站配色方案
Less提供了很多实用的函数专门用于定义和操作色彩.本文将介绍如何使用这些函数来 帮助你控制色彩,创造合适的色彩搭配,并且保持网站的一致性和专业性 color spinning spin()函数允许我 ...