在Delphi 2007中,我使用一个类来实现第二类支持的接口之一。这很有效。德尔福帮助指出:
默认情况下,使用implements关键字委托所有接口 方法。但是,您可以使用方法解析子句或声明 类中实现某些接口方法的方法 覆盖此默认行为。
但是,当我在我的第二个类中声明一个具有其中一个接口方法的匹配签名的方法时,它就不会被调用。
我想知道这是否是因为我在创建它时通过另一个界面访问该类。
以下是一个演示我的问题的测试程序:
program Project1;
{$APPTYPE CONSOLE}
type
IInterface1 = interface
['{15400E71-A39B-4503-BE58-B6D19409CF90}']
procedure AProc;
end;
IInterface2 = interface
['{1E41CDBF-3C80-4E3E-8F27-CB18718E8FA3}']
end;
TDelegate = class(TObject)
protected
procedure AProc;
end;
TMyClass = class(TInterfacedObject, IInterface1, IInterface2)
strict private
FDelegate: TDelegate;
property Delegate: TDelegate read FDelegate implements IInterface1;
public
constructor Create;
destructor Destroy; override;
procedure AProc;
end;
procedure TDelegate.AProc;
begin
writeln('TClassDelegate.AProc');
end;
constructor TMyClass.Create;
begin
inherited;
FDelegate := TDelegate.Create;
end;
destructor TMyClass.Destroy;
begin
FDelegate.Free;
inherited;
end;
procedure TMyClass.AProc;
begin
writeln('TMyClass.AProc');
end;
var
MyObj : IInterface2;
begin
MyObj := TMyClass.Create;
(MyObj as IInterface1).AProc;
end.
当我运行时,我得到输出:
TClassDelegate.AProc
我想要的是:
TMyClass.AProc
任何帮助表示感谢。
答案 0 :(得分:5)
您似乎必须以这种方式重新声明您的方法:
TMyClass = class(TInterfacedObject, IInterface1, IInterface2)
strict private
....
procedure test();
public
....
procedure IInterface1.AProc = test;
end;
procedure TMyClass.test;
begin
writeln('TMyClass.AProc');
end;
因此IInterface1.AProc
的{{1}}映射到TMyClass
(不是Test()
)
结果是FDelegate.AProc
答案 1 :(得分:1)
这可能是由于该物业的可见性。每次我使用implements
属性为protected
或public
时,我在VCL中找到的所有示例都相同(例如TAutoObjectEvent
。
尝试#2:
如果从AProc()
中删除TMyClass
方法会怎样?然后是否使用TDelegate
上的那个?
答案 2 :(得分:1)
您提到的文档部分似乎已过时。如果您尝试对implements
子句中使用的接口使用方法解析,则会出现编译器错误E2264: Cannot have method resolutions for interface '%s'。
上面链接中显示的解决方案 - 简单地给出与接口中声明的名称相同的过程 - 在Delphi XE中似乎也不起作用(它编译但不调用过程)。
答案 3 :(得分:1)
documentation明确指出您看到的行为符合设计:
如果delegate属性是类类型,则在搜索封闭类及其祖先之前,将搜索该类及其祖先实现指定接口的方法。
我想在完整的示例中,您有一个具有多个方法的接口,并且希望委托指定的多数,以及实现类重写的特定的接口。我不知道如何只用一个类来实现它,但是如果你引入第二个类就可以完成:
program Project1;
{$APPTYPE CONSOLE}
type
IInterface1 = interface
['{15400E71-A39B-4503-BE58-B6D19409CF90}']
procedure AProc;
procedure AnotherProc;
end;
TDelegate = class
protected
procedure AProc;
procedure AnotherProc;
end;
TMyClass = class(TInterfacedObject, IInterface1)
strict private
FDelegate: TDelegate;
property Delegate: TDelegate read FDelegate implements IInterface1;
public
constructor Create;
destructor Destroy; override;
procedure AProc;
end;
TMyOtherClass = class(TMyClass, IInterface1)
procedure IInterface1.AProc = AProc;
end;
procedure TDelegate.AProc;
begin
writeln('TDelegate.AProc');
end;
procedure TDelegate.AnotherProc;
begin
writeln('TDelegate.AnotherProc');
end;
constructor TMyClass.Create;
begin
inherited;
FDelegate := TDelegate.Create;
end;
destructor TMyClass.Destroy;
begin
FDelegate.Free;
inherited;
end;
procedure TMyClass.AProc;
begin
writeln('TMyClass.AProc');
end;
var
MyObj: IInterface1;
begin
MyObj := TMyOtherClass.Create;
MyObj.AProc;
MyObj.AnotherProc;
Readln;
end.
正如@teran指出的那样,如果你准备重命名你的方法,那么有一个更简单的解决方案。