Ken*_*ran 11 delphi inheritance interface delphi-2009
假设您有以下内容:
//Note the original example I posted didn't reproduce the problem so
//I created an clean example
type
IParent = interface(IInterface)
['{85A340FA-D5E5-4F37-ABDD-A75A7B3B494C}']
procedure DoSomething;
end;
IChild = interface(IParent)
['{15927C56-8CDA-4122-8ECB-920948027015}']
procedure DoSomethingElse;
end;
TGrandParent = class(TInterfacedObject)
end;
TParent = class(TGrandParent)
end;
TChild = class(TParent, IChild)
private
FChildDelegate: IChild;
public
property ChildDelegate:IChild read FChildDelegate implements IChild;
end;
TChildDelegate = class(TInterfacedObject, IChild)
public
procedure DoSomething;
procedure DoSomethingElse;
end;
Run Code Online (Sandbox Code Playgroud)
我认为这可以让你打电话,DoSomething
但似乎并非如此:
procedure CallDoSomething(Parent: TParent);
begin
if Parent is TChild then
TChild(Parent).DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)
很明显,编译器正在强制执行接口继承,因为除非实现了成员,否则这两个类都不会编译IParent
.尽管如此,编译器无法解析IParent
实例化和使用类时的成员.
我可以通过明确包含IParent
在类声明中来解决这个问题
TMyClass
:
TMyClass = class(TInterfacedObject, IChild, IParent)
Run Code Online (Sandbox Code Playgroud)
没关系,这不适用于任何事情.
dth*_*rpe 14
如果实现类没有声明它支持继承的接口,那么该类将不会与继承接口的变量进行赋值兼容.您发布的代码示例应该可以正常工作(使用IChild接口),但是如果您尝试从TMyClass的实例分配给IParent变量,那么您将遇到麻烦.
原因是因为COM和ActiveX允许实现实现后代接口(您的IChild)但拒绝该接口的祖先(IParent).由于Delphi接口旨在与COM兼容,因此这个愚蠢的工件来自于此.
我很确定我在10年或12年前写过一篇关于这篇文章的文章,但是我的Borland博客并没有幸免于过渡到Embarcadero服务器.
可能有一个编译器指令来改变这种行为,我不记得了.
问题不在接口声明或类实现中,而是在您的使用者代码中:
procedure CallDoSomething(Parent: TParent);
begin
if Parent is TChild then
TChild(Parent).DoSomething; // << This is wrong
end;
Run Code Online (Sandbox Code Playgroud)
不会起作用,因为TChild没有方法" DoSomething ".如果年掳实施ICHILD 直接,那么这将通常是可能的,因为年掳将直接实现方法和作为的一部分ICHILD接口.
但是请注意,如果TChild在PRIVATE范围内实现了DoSomething,它仍然可以通过接口访问,但是正常的范围规则意味着您仍然无法使用TChild引用调用它(来自class/uni之外).
在您的情况下,您只需要获取适当的接口,然后通过接口调用您需要的方法:
if Parent is TChild then
(Parent as IChild).DoSomething;
Run Code Online (Sandbox Code Playgroud)
但是,您正在使用类类型测试来确定(推断)接口的存在,依赖于实现细节(TChild实现IChild的知识).我建议您应该直接使用接口测试,将这种依赖性与这些实现细节隔离开来:
var
parentAsChild: IChild;
begin
if Parent.GetInterface(IChild, parentAsChild) then
parentAsChild.DoSomething;
end;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5590 次 |
最近记录: |