代码:
oIntfA, oIntfB: IInterface; oEntA ,oEntB:IElement; //根据控件的下标来获Pointer对应的接口; oIntfA := IInterface(Pointer(PropA.Items.Objects[ItemIndex])); oIntfB := IInterface(Pointer(PropB.Items.Objects[ItemIndex])); //转为相应的接口 if Supports(oIntfA, IElement) then begin oEntA := (oIntfA as IElement); oEntB := (oIntfB as IElement); if oEntA.ElementType = oEntB.ElementType then begin ........ end; end; |
接口是什么?
IInterface = interface
['{00000000-0000-0000-C000-000000000046}']
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
['{00000000-0000-0000-C000-000000000046}']:这是其实是接口的唯一标识,也就是我们说的TGUID;当把接口注册给系统后,我们可以通过注册表检索到00000000-0000-0000-C000-000000000046这样的键值。那么这就意味着,我们只需要知道一个TGUID的值就可以方便的访问这个接口。
关于变量:你可以在接口中定义其他的方法,但是Delphi中是不允许给接口添加变量成员的,因为接口是不允许有实现部分的。
关于继承: 同样,接口也可以继承、封装以及方法的覆盖。继承接口同类继承类似:
type INewInterface = interface(IInterface) // 定义一个新的接口INewInterface,并告诉编译器它是继承自IInterface接口 .... end; |
接口的继承大致就是这样,和TObject是所有类的根类一样,在Delphi中IInterface是所有接口的根类,那么类似于下面的继承:
type INewInterface = interface ... end; |
其实也是定义了一个继承自IInterface的新接口INewInterface(和类名前加一个大写字母T一样,我们习惯于在接口名前加一个大写字母I,当然这只是一个命名约定)
唯一标识:接口的TGUID是每一个接口的唯一标识,那么也就是说,TGUID是不能重复的。你不能简单的从别处抄袭过来,那样是错误的。如果你需要一个TGUID,你可以在Delphi的代码编辑框中同时按下CTRL+SHIFT+G来获得一个新的TGUID值,这个值是Delphi为你自动生成的。
那么怎么让接口为我们工作呢?
其实,接口的实现是需要借助于类来完成的(当然这看上去和C++中的多重继承的写法差不多)注意,既然接口是需要借助类来实现的,那么也就是说用来实现接口的类,必须实现接口中所有已定义的方法:
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?我们前面说过了:接口即没有构造方法,也没有析构方法。既然没有析构方法,那么就意味着我们不能用释放类的方式来释放接口。
那么直接把接口对象指空会造成内存泄露吗?
答案是否定的,因为接口提供了一个引用记数的机制:当某接口实例(也就是实现了这个接口的对象)被引用,比如被赋值给一个接口变量时,该接口实例的AddRef方法会被编译器自动调用,引用计数将增加一。引用取消时编译器则会调用_Release方法将引用计数减一。引用计数减到零时,表示已无其他接口变量引用此接口实例,此时编译器会自动释放它。
要注意的是,接口对象与类对象是不能混用的。当然像我们上面的例子里,NewFace也只能调用INewInterface接口中所定义过的方法,而不能调用类中定义的不存在于接口中的方法。
当然,一个类可以同时实现多个接口,多个接口彼此用逗号隔开。如:
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可以指定多个接口,彼此用逗号分隔。
implements指示字的好处是:
一、他允许以无冲突的方式进行接口聚合。(聚合是COM中的概念)
二、他能够延后占用实现接口所需要的资源,直到确实需要资源。
下面是关于委托的一个详细例子(该例在DELPHI7 + WIN2000 SP4 中调试通过):
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的封装后,将变的非常的有意义,呵呵
相关推荐
其实,两者之间还是有很大的区别的,对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析,试图给开发者提供一个在二者之间进行选择的依据。
理解并充分利用Robot Interface的功能,有助于提升生产效率,降低人工成本,增强企业的竞争力。对于想要进一步了解FANUC Robot Interface的读者,可以参考提供的"Robot Interface介绍.pdf"文件,获取更深入的技术...
本文将详细解析"yh_interface.dll"这一医保调用DLL在开发中的应用。 "yh_interface.dll"是一个专门用于医保调用的动态链接库(Dynamic Link Library),它是开发者整合医保功能到各类应用程序中的核心组件。DLL文件...
### C# Interface 学习经验浅谈 #### 接口概念与作用 接口(Interface)在C#中是一种特殊的抽象类型,它定义了一个类或结构必须实现的行为规范。通过接口,我们可以定义一组方法、属性、索引器和事件,但不能定义...
Xcode Interface Builder是苹果公司为其iOS和Mac应用开发提供...开发者通过熟悉和掌握Interface Builder的各项功能,可以更好地构建出符合预期的用户界面,同时也可以更深入地理解和利用Xcode这一强大的集成开发环境。
在Android开发中,接口(Interface)是实现组件间通信的重要机制。它允许类与类之间、组件与组件之间通过约定的方式来交互数据和控制流程。在这个名为"Android接口Interface的使用"的示例中,我们将深入探讨如何定义...
前者可能是插件的使用手册或用户指南,包含详细的操作步骤和注意事项,帮助用户理解和应用这个接口。后者则是插件的安装包,用户可以通过解压并按照指示安装,以便在Flotherm中启用这个功能。 综上所述,这个插件是...
在深入理解这个知识点之前,我们先来了解一下ADB和USB调试的基本概念。 ADB是Android开发过程中不可或缺的一部分,它是一个命令行工具,允许开发者通过USB或无线网络连接到安卓设备,执行一系列操作,如安装/卸载...
### ARM Debug Interface v5 #### 概述 ...通过对这些接口的理解和应用,开发者能够更加高效地完成嵌入式系统的开发和调试工作。此外,ADI v5还特别强调了版权保护的重要性,确保了技术的安全性和合法性。
综上所述,《ARM Debug Interface v5.2 Architecture Specification》是理解并利用SWD和JTAG接口进行STM32等ARM处理器调试的关键参考资料,对于嵌入式系统的开发者来说,深入学习此规范能提高工作效率,确保程序的...
本例程是基于策略模式设计的,旨在帮助理解何时以及如何有效地使用接口。策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。 首先,我们需要了解接口的基本概念。在Java、C#等面向对象编程语言中,接口...
这些技术术语和相关产品是ARM技术生态中的重要组成部分,是学习和理解ARM调试接口的重要基础知识。 最后,文档强调了产品及其用途的所有细节是基于良好诚信原则由ARM Limited提供的。文档还提醒用户,任何技术的...
在.NET框架中,接口(Interface)是定义行为规范的关键组件,尤其在ASP.NET开发中,接口扮演着重要的角色。它们提供了代码的抽象和多态性,使得类可以实现多个不同的行为,增强了代码的灵活性和可扩展性。让我们深入...
Citrix XenDesktop的Web Interface是一种用于管理和访问虚拟桌面和应用程序的组件。...理解并正确配置这些组件,可以大大提高虚拟桌面和应用程序交付的效率和安全性,进而提升用户的整体使用体验。
AS-Interface是一种工业现场总线技术,广泛应用于自动化领域,尤其是对于设备间简单的数字和模拟信号传输。AS-Interface寻址设备V3.0手册主要提供了关于如何正确安装、操作和维护该设备的技术指导和注意事项,以确保...
I/O设备通过特定的信号编码进行数据通信,而AS-Interface的主站负责解码这些信号,将它们转换成PLC可以理解的数据格式。 在PLC层面,AS-Interface可以与其他工业通信协议如PROFIBUS集成。例如,AS-Interface可以...
在Spring框架中,"interface21"通常指的是Spring 2.1版本的接口和源代码。这个阶段的Spring已经发展得相当成熟,引入了许多关键特性,对于理解Spring的工作原理和设计模式至关重要。以下是对Spring 2.1版本中一些...
2. **接口继承**:理解是否支持接口间的继承,以及如何实现。 3. **对象和类的实现**:学习如何让类或对象实现定义好的接口,以满足接口的要求。 4. **错误检查和类型安全**:了解"interface.js"如何确保对象符合...
在“理解接口interface,简单的一个demo”这个主题中,我们将深入探讨接口的基本用法以及如何在实际编程中应用。通过定义并实现多个接口,我们可以看到接口如何为不同类提供通用的行为模板,而各个类可以根据自己的...