Delphi 中接口实现:Implementing Interfaces

        

目录

一、类声明(Class Declarations)

二、方法解决说明(Method Resolution Clause)

三、更改继承实现(Changing Inherited Implementations)

四、通过委托实现接口(Implementing Interfaces by Delegation)

五、委托接口类型属性(Delegating to an Interface-Type Property)

六、委托给类类型属性(Delegating to a Class-Type Property)


        接口一经声明,必须在类中实现后才能使用。在类的声明中,在类的祖先名称之后指定了类所实现的接口。

一、类声明(Class Declarations)

此类声明的形式如下 :

type className = class (ancestorClass, interface1, ..., interfaceN)
   memberList
end;

例如:

type
  TMemoryManager = class(TInterfacedObject, IMalloc, IErrorInfo)
    // ...

        声明了一个名为 TMemoryManager 的类,该类实现了 IMalloc 和 IErrorInfo 接口。当一个类实现一个接口时,它必须实现(或继承实现)接口中声明的每个方法。

以下是 System.TInterfacedObject 的声明(在 Windows 平台上,在其他平台上,声明略有不同):

type
 TInterfacedObject = class(TObject, IInterface)
 protected
   FRefCount: Integer;
   function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
   function _AddRef: Integer; stdcall;
   function _Release: Integer; stdcall;
 public
   procedure AfterConstruction; override;
   procedure BeforeDestruction; override;
   class function NewInstance: TObject; override;
   property RefCount: Integer read FRefCount;
 end;

TInterfacedObject 实现了 IInterface 接口。因此,TInterfacedObject 声明并实现了三个 IInterface 方法中的每一个。

实现接口的类也可用作基类。(上面的第一个示例将 TMemoryManager 声明为 TInterfacedObject 的直接继承)。每个接口都继承自 IInterface,实现接口的类必须实现 QueryInterface、_AddRef 和 _Release 方法。单元 System 中的 TInterfacedObject 实现了这些方法,因此是一个方便的基类,可以从中派生出其他实现接口的类。

实现接口时,接口的每个方法都会被映射到实现类中的一个方法上,该方法具有相同的结果类型、相同的调用约定、相同的参数数以及每个位置上相同类型的参数。默认情况下,每个接口方法都会映射到实现类中的同名方法。
 

二、方法解决说明(Method Resolution Clause)

通过在类声明中包含方法解析子句,可以覆盖默认的基于名称的映射。当一个类实现了两个或多个具有相同命名方法的接口时,可以使用方法解析子句来解决命名冲突。

方法解析子句的形式如下 :

procedure interface.interfaceMethod = implementingMethod;

或者

function interface.interfaceMethod = implementingMethod;

其中,implementingMethod 是该类或其祖先类中声明的方法。implementingMethod 可以是类声明中稍后声明的方法,但不能是其他模块中声明的祖先类的私有方法。

例如 :

type
  TMemoryManager = class(TInterfacedObject, IMalloc, IErrorInfo)
    function IMalloc.Alloc = Allocate;
    procedure IMalloc.Free = Deallocate;
   // ...
  end;

将 IMalloc 的 Alloc 和 Free 方法映射到 TMemoryManager 的 Allocate 和 Deallocate 方法上。

方法解析子句不能改变父类引入的映射。

三、更改继承实现(Changing Inherited Implementations)

子类可以通过覆盖实现方法来改变特定接口方法的实现方式。这要求实现方法是虚拟的或动态的。

类还可以重新实现从祖先类继承的整个接口。这需要在子类的声明中重新列出接口。例如:

type
  IWindow = interface
    ['{00000115-0000-0000-C000-000000000146}']
    procedure Draw;
    // ...
  end;
  TWindow = class(TInterfacedObject, IWindow)
    // TWindow implements IWindow pocedure Draw;
    // ...
  end;
  TFrameWindow = class(TWindow, IWindow)
    // TFrameWindow reimplements IWindow procedure Draw;
    // ...
  end;

        重新实现接口会隐藏同一接口的继承实现。因此,父类中的方法解析条款对重新实现的接口没有任何影响。

四、通过委托实现接口(Implementing Interfaces by Delegation)

implements 指令允许将接口的实现委托给实现类中的一个属性。例如 :

property MyInterface: IMyInterface read FMyInterface implements IMyInterface;

声明了一个名为 MyInterface 的属性,该属性实现了接口 IMyInterface。

implements 指令必须是属性声明中的最后一个指定符,并且可以列出多个接口,中间用逗号隔开。委托属性 :

  • 必须是类或接口类型。
  • 不能是数组属性,也不能有索引说明符。
  • 必须有读取说明符。如果属性使用读取方法,则该方法必须使用默认寄存器调用约定,不能是动态的(尽管可以是虚拟的),也不能指定消息指令。

用于实现委托接口的类应该派生自 System.TAggregatedObject。

五、委托接口类型属性(Delegating to an Interface-Type Property)

如果委托属性属于接口类型,则该接口或其派生接口必须出现在声明该属性的类的祖先列表中。委托属性必须返回一个对象,该对象的类完全实现了 implements 指令指定的接口,并且不含方法解析子句。例如 :

type
  IMyInterface = interface
    procedure P1;
    procedure P2;
  end;
  TMyClass = class(TObject, IMyInterface)
    FMyInterface: IMyInterface;
    property MyInterface: IMyInterface read FMyInterface implements IMyInterface;
  end;
var
  MyClass: TMyClass;
  MyInterface: IMyInterface;
begin
  MyClass := TMyClass.Create;
  MyClass.FMyInterface := ...// some object whose class implements IMyInterface
  MyInterface := MyClass;
  MyInterface.P1;
end;

六、委托给类类型属性(Delegating to a Class-Type Property)

如果委托属性属于一个类的类型,则在搜索外层类及其祖先之前,先搜索该类及其祖先中实现指定接口的方法。因此,可以在属性指定的类中实现某些方法,而在声明属性的类中实现其他方法。方法解析子句可以按通常的方式用于解决歧义或指定特定方法。一个接口不能由多个类类型属性实现。例如 :

type
  IMyInterface = interface
    procedure P1;
    procedure P2;
  end;
  TMyImplClass = class
    procedure P1;
    procedure P2;
  end;
  TMyClass = class(TInterfacedObject, IMyInterface)
    FMyImplClass: TMyImplClass;
    property MyImplClass: TMyImplClass read FMyImplClass implements IMyInterface;
    procedure IMyInterface.P1 = MyP1;
    procedure MyP1;
  end;
procedure TMyImplClass.P1;
     // ...
procedure TMyImplClass.P2;
     // ...
procedure TMyClass.MyP1;
     // ...
var
  MyClass: TMyClass;
  MyInterface: IMyInterface;
begin
  MyClass := TMyClass.Create;
  MyClass.FMyImplClass := TMyImplClass.Create;
  MyInterface := MyClass;
  MyInterface.P1;  // calls TMyClass.MyP1;
  MyInterface.P2;  // calls TImplClass.P2;
end;

猜你喜欢

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