Delphi 中的对象接口:Object Interfaces

         

目录

一、接口类型(Interface Types)

二、接口和继承(IInterface and Inheritance)

三、接口标识和 GUID(Interface Identification and GUIDs)

四、接口调用约定(Calling Conventions for Interfaces)

五、接口属性(Interface Properties)

六、前向声明(Forward Declarations)


        对象接口或简称接口,定义了类可以实现的方法。接口被声明为类,但不能直接实例化,也没有自己的方法定义。相反,任何支持接口的类都有责任提供接口方法的实现。接口类型的变量可以引用实现该接口的类的对象;但是,只有接口中声明的方法才能被调用。

        接口具有多重继承的一些优点,但没有语义上的困难。对于使用分布式对象模型(如 SOAP)来说,接口也是必不可少的。使用分布式对象模型,支持接口的自定义对象可以与 C++、Java 和其他语言编写的对象进行交互。

一、接口类型(Interface Types)

接口与类一样,只能在程序或单元的最外层范围内声明,而不能在存储过程或函数声明中声明。接口类型声明的形式如下 :

type interfaceName = interface (ancestorInterface) ['{GUID}'] memberList end;

警告: 为了支持 Win32 COM 的互操作性,需要使用 ancestorInterface GUID 规范。如果要通过 COM 访问接口,请务必指定 ancestorInterface GUID

在大多数方面,接口声明与类声明相似,但有以下限制: 

  1. 成员列表只能包括方法和属性。接口中不允许有字段。
  2. 由于接口没有字段,因此属性的读写指定必须是方法。
  3. 接口的所有成员都是公用的。不允许使用可见性指定符和存储指定符。(但数组属性可以声明为默认)。
  4. 接口没有构造函数或析构函数。除了通过实现其方法的类外,它们不能被实例化。
  5. 方法不能声明为虚拟、动态、抽象或覆盖(virtual, dynamic, abstract, or override)。由于接口不实现自己的方法,因此这些名称没有任何意义。

下面是一个接口声明的示例: 

type IMalloc = interface(IInterface)
    ['{00000002-0000-0000-C000-000000000046}'] 
    function Alloc(Size: Integer): Pointer; stdcall; 
    function Realloc(P: Pointer; Size: Integer): Pointer; stdcall; 
    procedure Free(P: Pointer); stdcall;
    function GetSize(P: Pointer): Integer; stdcall;
    function DidAlloc(P: Pointer): Integer; stdcall;
    procedure HeapMinimize; stdcall;
  end;

在某些接口声明中,interface 保留字由 dispinterface 代替。

二、接口和继承(IInterface and Inheritance)

        接口与类一样,继承其祖先的所有方法。但接口与类不同,并不实现方法。接口继承的是实现方法的义务,这种义务会传递给任何支持接口的类。

        接口的声明可以指定一个祖先接口。如果没有指定祖先接口,该接口就是 IInterface 的直接后代,而 IInterface 是在 System 单元中定义的,是所有其他接口的最终祖先。在 Win32 中,IInterface 声明了三个方法: QueryInterface、_AddRef 和 _Release。

注意:IInterface 等同于 IUnknown。一般来说,独立于平台的应用程序应使用 IInterface,而包含 Win32 依赖性的特定程序则应保留使用 IUnknown。

        QueryInterface 提供了获取对象所支持的不同接口引用的方法。_AddRef 和 _Release 为接口引用提供了生命周期内存管理。实现这些方法的最简单方法是从 System 单元的 TInterfacedObject 派生实现类。也可以通过以空函数的形式实现这些方法中的任何一种,但 COM 对象必须通过 _AddRef 和 _Release 进行管理。

警告: 需要使用 QueryInterface、_AddRef 和 _Release 来支持 Win32 COM 互操作性。如果要通过 COM 访问接口,请务必实现这些方法。

三、接口标识和 GUID(Interface Identification and GUIDs)

接口声明可以指定一个全局唯一标识符(GUID),该标识符由一个字面字符串表示,该字符串括在成员列表前的括号中。声明中的 GUID 部分必须具有以下形式 :

 ['{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}']

        其中每个 x 是十六进制数字(0 到 9 或 A 到 F)。类型库编辑器会自动为新界面生成 GUID。您也可以在代码编辑器中按 Ctrl+Shift+G 生成 GUID。

        GUID 是唯一标识接口的 16 字节二进制值。如果接口有 GUID,就可以使用接口查询来获取其实现的引用。

注:GUID 仅用于 COM 的互操作性。

        系统单元中声明的 TGUID 和 PGUID 类型用于操作 GUID。

type 
     PGUID = ^TGUID;
     TGUID = packed record
       D1: Cardinal;
       D2: Word;
       D3: Word;
       D4: array[0..7] of Byte;
   end;

支持有两种调用方式:

if Supports(Allocator, IMalloc) then ...

或者

if Supports(Allocator, IID_IMalloc) then ...

注:SysUtils 单元提供了一个名为 Supports 的重载函数,当类类型和实例支持由 GUID 表示的特定接口时,该函数返回 true 或 false。Supports 函数的使用方式与 Delphi is 和 as 操作符相同。不同之处在于,Supports 函数的右操作数可以是 GUID 或与 GUID 相关联的接口类型,而 is 和 as 操作数的右操作数则是类型名称。有关 is 和 as 的更多信息,请参阅类引用。

四、接口调用约定(Calling Conventions for Interfaces)

        接口方法的默认调用约定是 register,但模块间共享的接口(尤其是用不同语言编写的接口)应使用 stdcall 声明所有方法。在 Win32 中,可以使用 safecall 来实现双接口的方法。

五、接口属性(Interface Properties)

        接口中声明的属性只能通过接口类型的表达式访问,不能通过类类型变量访问。此外,接口属性只能在编译了接口的程序中可见。

        在接口中,属性的读取和写入指定必须是方法,因为字段是不可用的。

六、前向声明(Forward Declarations)

        以保留字 interface 和分号结尾的接口声明,如果没有指定祖先、GUID 或成员列表,则属于正向声明。前向声明必须由同一类型声明部分中同一接口的定义声明来解决。换句话说,在前向声明和定义声明之间,除了其他类型声明外,不能有任何其他声明。

        前向声明允许相互依赖的接口。例如 :

type 
   IControl = interface; 
   IWindow = interface 
       ['{00000115-0000-0000-C000-000000000044}'] 
       function GetControl(Index: Integer): IControl; 
         //. . . 
     end; 
   IControl = interface 
       ['{00000115-0000-0000-C000-000000000049}'] 
       function GetWindow: IWindow; 
       //. . . 
     end;

        不允许相互派生接口。例如,从 IControl 派生 IWindow 和从 IWindow 派生 IControl 都是不合法的。

猜你喜欢

转载自blog.csdn.net/sensor_WU/article/details/132492050