对于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接口使用实例介绍的更多相关文章

  1. 【转】Web Service单元测试工具实例介绍之SoapUI

    转自:http://blog.csdn.net/oracle_microsoft/article/details/5689585 SoapUI 是当前比较简单实用的开源Web Service 测试工具 ...

  2. osg实例介绍

    osg实例介绍 转自:http://blog.csdn.net/yungis/article/list/1 [原]osgmotionblur例子 该例子演示了运动模糊的效果.一下内容是转自网上的:原理 ...

  3. tcpdump wireshark 实用过滤表达式(针对ip、协议、端口、长度和内容) 实例介绍

    tcpdump wireshark 实用过滤表达式(针对ip.协议.端口.长度和内容) 实例介绍 标签: 网络tcpdst工具windowslinux 2012-05-15 18:12 3777人阅读 ...

  4. Web Service单元测试工具实例介绍之SoapUI

    原文  Web Service单元测试工具实例介绍之SoapUI SoapUI是当前比较简单实用的开源Web Service测试工具,提供桌面应用程序和IDE插件程序两种使用方式.能够快速构建项目和组 ...

  5. delphi 接口Interface

    学习 delphi 接口 一切都是纸老虎!!! 第四章          接口 前不久,有位搞软件的朋友给我出了个谜语.谜面是“相亲”,让我猜一软件术语.我大约想了一分钟,猜 出谜底是“面向对象”.我 ...

  6. Spring IOC(通过实例介绍,属性与构造方法注入)

    概括说明:下面通过实例介绍下属性方法注入.构造方法注入 1.源码结构图 2.代码介绍 (1).Dao接口 :UserDAO (2).Dao接口实现:UserDAOImpl (3).实体类:User ( ...

  7. Delphi 接口使用中,对象生命周期管理,如何释放需要注意的问题

    网上有篇文章<Delphi接口编程的两大陷阱>,里面提到接口的生存期管理的问题.但该文章里面提到的两个问题,其实都是对 Delphi 不理解导致的.   先说该篇文章中提到的第一个问题为什 ...

  8. delphi 接口

    第四章          接口 前不久,有位搞软件的朋友给我出了个谜语.谜面是“相亲”,让我猜一软件术语.我大约想了一分钟,猜 出谜底是“面向对象”.我觉得挺有趣,灵机一动想了一个谜语回敬他.谜面是“ ...

  9. 多线程的基本概念和Delphi线程对象Tthread介绍

    多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru    WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行 ...

随机推荐

  1. 复位电路设计——利用PLL锁定信号(lock)产生复位信号

    利用PLL锁定信号(lock)产生复位信号 在FPGA刚上电的时候,系统所需的时钟一般都要经过PLL倍频,在时钟锁定(即稳定输出)以前,整个系统应处于复位状态.因此,我们可以利用PLL的锁定信号来产生 ...

  2. Codeforces GYM 100741A . Queries

    time limit per test 0.25 seconds memory limit per test 64 megabytes input standard input output stan ...

  3. BZOJ 2157: 旅游 (2017.7.21 6:30-2017.7.21 15:38 今日第一题。。)

    Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1754  Solved: 765 Description Ray 乐忠于旅游,这次他来到了T 城.T ...

  4. smile domain name www.bn-nd.com for sell. Please contact boyanzheng at foxmail.com 微笑的域名。请联系邮箱。

  5. 解决selenium.common.exception.WebDriverException:Message:'chromedriver' executable needs to be in Path

    'chromedriver' executable needs to be in Path 声明:本人萌新,刚学python不久记录一下自己的坑,发出来若能帮助到一些人尽早解决问题那便是极好的,( ̄▽ ...

  6. const函数的使用

    const知道吗?解释其作用. 1.const 修饰类的成员变量,表示成员常量,不能被修改. 2.const修饰函数承诺在本函数内部不会修改类内的数据成员,不会调用其它非 const 成员函数. 3. ...

  7. Java BufferedReader文件读取 带缓冲区的字符流

    package org.jimmy.autosearch2019.test; import java.io.BufferedReader; import java.io.FileInputStream ...

  8. AspNetCore容器化(Docker)部署(一) —— 入门

    一.docker注册安装 Windows Docker Desktop https://www.docker.com/products/docker-desktop Linux Docker CE h ...

  9. JavaSE-29 Java8的Lambda表达式

    概念说明 Lambda表达式是Java8提供的新特性,支持将代码块作为方法的参数. Lambda表达式支持使用简洁的代码创建只有一个方法的接口(函数式接口). 只包含一个方法的接口也称为函数式接口. ...

  10. mybatis-5 手写代理

    @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Select { public St ...