I have one class instance and two references to it. There is one object reference (aMII : TMyInterfaceImpl) and one interface reference (iMI : IMyInterface).
When I use the object reference to assign one of its methods to a method type variable (methodRef : TMyMethodRef), it works fine.
But if I want to use the interface reference in the same situation, the compiler throws an error:
[dcc32 Error] Unit1.pas(66): E2010 Incompatible types: 'TMyMethodRef' and 'procedure, untyped pointer or untyped parameter'
The minimal example:
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;
In my original source I have to use interfaces (I don't have the object references, because of the abstract factory design pattern : function TMyFactory.createMyInterface : IMyInterface).
And I have to use one of its methods as a callback function on some events (passed as a parameter to the setter method : procedure TMyInterfaceImpl2.setOnEvent( onEvent_ : TMyMethodRef ).
How can I do it? How can I assign one of the methods of an interface reference to a method type variable?
I know there is a solution to implement one another interface to access the object reference, but it does not secure (I could not be sure all the time the class implements both interfaces) and I don't want this solution:
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;