1

我正在尝试从 IOrderedDictionary 继承一个接口并实现继承的接口,见下文:

uses
  Spring.Collections;

type
  IAttributeCollection = interface(IOrderedDictionary<String,String>)
  end;

  INodeContents = interface(IAttributeCollection)
    function Test: Boolean;
  end;

  TAttributeCollection = class(TInterfacedObject, IAttributeCollection)
  private
    FAttributes: IAttributeCollection;
    function GetAttributes: IAttributeCollection;
  public
    constructor Create;
    property Attributes: IAttributeCollection read GetAttributes implements
        IAttributeCollection;
  end;

  TNodeContents = class(TAttributeCollection, INodeContents)
  public
    function Test: Boolean;
  end;

此代码无法编译,在 TNodeContens 中,编译器错过了 Spring.Collections.IDictionary.GetItem 的实现(除了一些其他但不是所有成员)。

这看起来很奇怪,当我直接在单元中定义通用接口时,代码符合得很好(见下文)。

type
  IOrderedDictionary<TKey, TValue> = interface(IInvokable)
  end;

  IAttributeCollection = interface(IOrderedDictionary<String,String>)
  end;

  INodeContents = interface(IAttributeCollection)
    function Test: Boolean;
  end;

  TAttributeCollection = class(TInterfacedObject, IAttributeCollection)
  private
    FAttributes: IAttributeCollection;
    function GetAttributes: IAttributeCollection;
  public
    constructor Create;
    property Attributes: IAttributeCollection read GetAttributes implements
        IAttributeCollection;
  end;

  TNodeContents = class(TAttributeCollection, INodeContents)
  public
    function Test: Boolean;
  end; 
4

2 回答 2

0

您正在派生一个新接口

type
  IAttributeCollection = interface(IOrderedDictionary<String,String>)
  end;

这会让你的生活比你需要的复杂得多。改用别名:

type
  IAttributeCollection = IOrderedDictionary<String,String>;

  TAttributeCollection = class(TInterfacedObject, IAttributeCollection)
  private
    FAttributes: IAttributeCollection;
  public
    constructor Create;
    property Attributes: IAttributeCollection read FAttributes implements IAttributeCollection;
  end;

constructor TAttributeCollection.Create;
begin
  FAttributes := TCollections.CreateOrderedDictionary<String,String>;
end;

当你需要引入另一个接口时,不要从IAttributeCollection. 像这样做:

type
  INodeContents = interface
    ['{---GUID---}']
    function Test: Boolean;
  end;

  TNodeContents = class(TAttributeCollection, INodeContents)
  public
    function Test: Boolean;
  end;

您需要 GUID 以便您可以查询INodeContents.


另一种方法可能是从实现类继承。看起来像这样:

type
  IAttributeCollection = interface(IOrderedDictionary<String,String>)
  end;

  INodeContents = interface(IAttributeCollection)
    function Test: Boolean;
  end;

  TAttributeCollection = class(TOrderedDictionary<String,String>, IAttributeCollection)
  end;

  TNodeContents = class(TAttributeCollection, INodeContents)
  public
    function Test: Boolean;
  end;

但是,我必须声明,我觉得这两种方法中的任何一种都不是解决您问题的正确方法。感觉好像您在滥用继承并在不合适的地方使用它。我不确定什么是正确的解决方案,因为您询问的是您的解决方案而不是您的问题。

于 2018-04-17T08:20:48.290 回答
0

I agree with David that you are going about this the wrong way. The way you would tackle this would be to create a brand new interface with the extra functionality that you need and implement (either explicitly or by inheritance) the two interfaces.

What you assume is that the functions inherited from an ancestor that have the same name as the interface you are now implementing will also satisfy the second interface. This is not so, and indeed cannot be so. Interfaces may coincidentally have the same name, and there are special constructs to handle such cases.

So what you have done effectively is to say you need to define each function in the original interface twice.

Instead, just do not inherit from the original interface. you don't need to.

uses
  Spring.Collections;

type
  IAttributeCollection = interface(IOrderedDictionary<String,String>)
  end;

  INodeContents = interface
    function Test: Boolean;
  end;

  TAttributeCollection = class(TInterfacedObject, IAttributeCollection)
  private
    FAttributes: IAttributeCollection;
    function GetAttributes: IAttributeCollection;
  public
    constructor Create;
    property Attributes: IAttributeCollection read GetAttributes implements
        IAttributeCollection;
  end;

  TNodeContents = class(TAttributeCollection, INodeContents)
  public
    function Test: Boolean;
  end;

Now you just need to additionally implement the function Test, which is what you want to achieve.

于 2018-04-17T09:08:45.737 回答