我有一个类实例和两个引用它.有一个对象reference(aMII : TMyInterfaceImpl)和一个接口引用(iMI : IMyInterface).当我使用对象引用将其方法之一分配给方法类型变量(methodRef : TMyMethodRef)时,它工作正常.
但是如果我想在相同的情况下使用接口引用,编译器会抛出一个错误:
[dcc32错误] Unit1.pas(66):E2010不兼容的类型:'TMyMethodRef'和'过程,无类型指针或无类型参数'
最小的例子:
type
TMyMethodRef = procedure of object;
//TMyMethodRef = procedure of interface; // Invalid definition, just a desperate attempt
IMyInterface = interface
['{BEA60A2B-C20F-4E02-A938-65DD4332ADB0}']
procedure foo;
end;
TMyInterfaceImpl = class ( TInterfacedObject, IMyInterface )
procedure foo;
end;
procedure TMyInterfaceImpl.foo;
begin
end;
procedure TForm1.Button1Click(Sender: TObject);
var
aMII : TMyInterfaceImpl;
iMI : IMyInterface;
methodRef : TMyMethodRef;
begin
aMII := TMyInterfaceImpl.Create;
iMI := aMII;
methodRef := aMII.foo; // It compiles
methodRef := iMI.foo; // It does not compile
end;
Run Code Online (Sandbox Code Playgroud)
在我的原始源代码中,我必须使用接口(我没有对象引用,因为抽象的工厂设计模式:) function TMyFactory.createMyInterface : IMyInterface.
我必须使用它的一个方法作为一些事件的回调函数(作为参数传递给setter方法:procedure TMyInterfaceImpl2.setOnEvent( onEvent_ : TMyMethodRef ).
我该怎么做?如何将接口引用的方法之一分配给方法类型变量?
我知道有一个解决方案来实现另一个接口来访问对象引用,但它不安全(我不能确定该类实现两个接口的所有时间)并且我不想要这个解决方案:
type
TMyMethodRef = procedure of object;
IMyInterface = interface
['{BEA60A2B-C20F-4E02-A938-65DD4332ADB0}']
procedure foo;
end;
TMyInterfaceImpl = class;
IInstanceAccessor<T> = interface
['{61E36FF2-A9D3-4B46-BAE8-217CBE7A1F18}']
function getInstance : T;
end;
TMyInterfaceImpl = class ( TInterfacedObject, IMyInterface, IInstanceAccessor<TMyInterfaceImpl> )
procedure foo;
function getInstance : TMyInterfaceImpl;
end;
procedure TMyInterfaceImpl.foo;
begin
end;
function TMyInterfaceImpl.getInstance : TMyInterfaceImpl;
begin
result := self;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
iMI : IMyInterface;
aMII : TMyInterfaceImpl;
methodRef : TMyMethodRef;
begin
iMI := TMyInterfaceImpl.Create;
aMII := ( iMI as IInstanceAccessor<TMyInterfaceImpl> ).getInstance;
methodRef := aMII.foo;
end;
Run Code Online (Sandbox Code Playgroud)
你不能这样做.
你可以做的是用这样的方法声明一个适配器类,并使用该方法作为回调.
type
TMyInterfaceAdapter = class
private
FIntf: IMyInterface;
public
procedure Foo;
property Intf: IMyInterface read FIntf write FIntf;
end;
procedure TMyInterface.Foo;
begin
Assert(Assigned(FIntf), 'no interface assigned');
FIntf.Foo;
end;
Run Code Online (Sandbox Code Playgroud)