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对话框中设置全局 ...
随机推荐
- 创建新进程,就三个函数CreateProcessAsUser CreateProcessWithLogonW CreateProcessWithTokenW(附网友的流程)
CreateProcessAsUser 怎么会还需要密码呢~~~ 先WTSGetActiveConsoleSessionId 得到当前的处理激活状态的SessionId OpenProcessToke ...
- Struts2笔记——Action校验器
在struts2中,我们可以实现对action的所有方法进行校验或者对action的指定方法进行校验. 对于输入校验struts2提供了两种实现方法: 1.采用手工编写代码实现. 2.基于XML配置 ...
- CSS3:empty
:empty ---空的元素样式 <!DOCTYPE html> <html> <head lang="en"> <meta charse ...
- 解密ThreadLocal
原文:http://qifuguang.me/2015/09/02/%5BJava%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83%5D%E ...
- linux内核编程笔记【原创】
以下为本人学习笔记,如有转载请注明出处,谢谢 DEFINE_MUTEX(buzzer_mutex); mutex_lock(&buzzer_mutex); mutex_unlock(& ...
- iPhone 屏幕上的 Home 键在哪里?(已解决)
「问」:iPhone屏幕上的Home键如何开启? 「答」:在[设置]-[通用]-[辅助功能]-[AssistiveTouch],打开即可.不需要下载什么App. [Settings] - [Gener ...
- tomcat7 1000并发量配置 tomcat7配置优化
修改tomcat/conf/server.xml配置文件. <Executor name="tomcatThreadPool" namePrefix="catali ...
- 6.cadence原理图下[原创]
一.平坦式原理图与分页式原理图 1 和2为平坦式原理图,平等 1和3为分页式原理图 有上下关系 ------------------------------------ 1.平坦式原理图 每张原理 ...
- asp存储过程
dim s_ip,MyComm s_ip=request.ServerVariables("REMOTE_ADDR") Set MyComm = Server.CreateObje ...
- NDK(2)使用eclipse + ndk开发过程演示,含CPU架构编译
环境linux + eclipse + adt + ndk 1,在ide中配置ndk 下载ndk,在eclipse中配置 2,使用ndk编程 2.1 给项目添加ndk 支持 右键 项目名 --> ...