Delphi 接口继承:为什么我不能访问祖先接口的成员? [英] Delphi interface inheritance: Why can't I access ancestor interface's members?

查看:18
本文介绍了Delphi 接口继承:为什么我不能访问祖先接口的成员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您有以下内容:

//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;

我认为这将允许您调用 DoSomething,但情况似乎并非如此:

I would think that this would allow you to call DoSomething but this doesn't seem to be the case:

procedure CallDoSomething(Parent: TParent);
begin
  if Parent is TChild then
    TChild(Parent).DoSomething;
end;

很明显,编译器正在强制执行接口继承,因为除非实现了IParent 的成员,否则两个类都不会编译.尽管如此,当类被实例化和使用时,编译器无法解析 IParent 的成员.

Its clear that the compiler is enforcing the interface inheritance because neither class will compile unless the members of IParent are implemented. Despite this the compiler is unable to resolve members of the IParent when the class is instantiated and used.

我可以通过在类声明中显式包含 IParent 来解决这个问题TMyClass:

TMyClass = class(TInterfacedObject, IChild, IParent)

没关系,这对任何事情都不起作用.

Nevermind, this doesn't work around anything.

推荐答案

问题不在于接口声明或类实现,而在于您的消费者代码:

The problem is not in the interface declarations or class implementations, but in your consumer code:

procedure CallDoSomething(Parent: TParent);
begin
  if Parent is TChild then
    TChild(Parent).DoSomething;  // << This is wrong
end;

不会工作,因为 TChild 没有方法DoSomething".如果 TChild 直接实现 IChild ,那么这通常是可能的,因为 TChild直接将方法AND作为IChild接口的一部分实现.

Is not going to work because TChild does not have a method "DoSomething". If TChild implemented IChild directly, then this would normally be possible because TChild would implement the method directly AND as part of the IChild interface.

但是请注意,如果 TChildPRIVATE 范围内实现了 DoSomething,它仍然可以通过界面访问,但正常的范围规则意味着您仍然无法使用 TChild 引用调用它(从类/uni 外部).

Note however, that if TChild implemented DoSomething in PRIVATE scope, it would remain accessible thru the interface but normal scoping rules would mean that you still couldn't invoke it (from outside the class/uni) using a TChild reference either.

在您的情况下,您只需要获取适当的接口,然后通过接口调用您需要的方法:

In your case, you simply need to obtain the appropriate interface and then invoke the method you require thru the interface:

  if Parent is TChild then
    (Parent as IChild).DoSomething;

但是,您正在使用类类型测试来确定(推断)接口的存在,这依赖于实现细节(TChild 实现了 IChild 的知识).我建议你应该直接使用接口测试,将这种依赖与那些实现细节隔离开来:

However, you are using a class type test to determine (infer) the presence of an interface, relying on an implementation detail (knowledge that TChild implements IChild). I suggest you should instead be using interface testing directly, to isolate this dependency from those implementation details:

  var
    parentAsChild: IChild;

  begin
    if Parent.GetInterface(IChild, parentAsChild) then
      parentAsChild.DoSomething;
  end;

这篇关于Delphi 接口继承:为什么我不能访问祖先接口的成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆