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

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

问题描述

假设您有以下内容:

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

它清楚的是编译器正在强制执行接口继承,因为除了$ code> 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.

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

I can work around this by explicitly including IParent in the class declaration of TMyClass:

TMyClass = class(TInterfacedObject, IChild, IParent)

Nevermind,这不能解决任何问题。

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 没有方法 strong> DoSomething 。如果 TChild 直接实施 IChild ,那么通常可能是因为 TChild 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.

如果 TChild 中实现 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接口继承:为什么我不能访问ancestor界面的成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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