11.2.2 接口的委托
我用类似的方式定义了一个简单类实现IJumper接口:
TJumperImpl = class(TAggregatedObject, IJumper)
private
FPos: Integer;
public
function Jump: string;
function Walk: string;
procedure SetPos(Value: Integer);
function GetPos: Integer;
end;
这个类的实现与之前的不同之处在于使用了一个特殊的基类TAggregatedObject。这是一个特定目的类,用于定义内部一个内部对象支持接口,我稍后将展示其语法。
TAggregatedObject 类是 System 单元中定义的 IInterface 接口的另一种实现。与 TInterfacedObject 类相比,它在引用计数的实现(基本上是将所有引用计数委托给容器或控制器)和接口查询的实现(如果容器支持多个接口)方面有所不同。
注解 TAggregatedObject 类是 System 单元中定义的 IInterface 的另一种实现。与 TInterfacedObject 相比,它在引用计数实现(基本上将所有引用计数委托给容器或控制器)和接口查询实现(如果容器支持多个接口的情况下)方面存在差异。
我将以一个不同的方式使用这个类。在下面的 TMyJumper 类中,我不想用类似的方法重复 IJumper 接口的实现。相反,我打算将该接口的实现委托给一个已经实现了该接口的类。这不能通过继承来实现(因为我们不能有两个基类);但是你可以使用Object Pascal语言的一个特殊功能:接口委托。下面的TMyJumper类通过属性去引用一个已经实现了接口的内部对象,从而就间接实现了 IJumper 接口,类本身并没有去实现该接口的实际方法:
TMyJumper = class(TInterfacedObject, IJumper)
private
FJumpImpl: TJumperImpl;
public
constructor Create;
destructor Destroy; override;
property Jumper: TJumperImpl read FJumpImpl implements IJumper;
end;
该类定义表明,TMyJumper 类通过 FJumpImpl 字段实现了 IJumper 接口。当然,该字段必须实际实现接口的所有方法。要接口委托起作用,需要在创建 TMyJumper 对象时为该字段创建一个合适的对象(构造函数参数是TAggregatedObject 基类所要求的):
constructor TMyJumper.Create;
begin
FJumpImpl := TJumperImpl.Create(Self);
end;
该类还有一个析构函数,用于释放内部对象,该对象是用普通字段而不是接口引用的(因为引用计数在这种情况下不起作用)。
这个例子很简单,但一般来说,当你开始修改某些方法或添加其他方法时,这些方法仍将对内部FJumpImpl 对象的数据进行操作,情况就会变得更加复杂。这里的总体概念是,你可以在多个类中重复使用一个接口的实现。使用间接实现的接口的代码与标准代码完全相同:
procedure TForm1.Button2Click(Sender: TObject);
var
Intf: IJumper;
begin
Intf := TMyJumper.Create;
Intf.Position := 0;
Show(Intf.Walk);
Show(Intf.Jump);
Show(Intf.Walk);
end;