Delphi - 接口内部的接口

时间:2015-08-13 08:54:50

标签: delphi interface interface-implementation

我是关于接口的新手。我google了很多,但我无法弄清楚在以下情况下该怎么做。

我创建了几个相互使用的接口:

IPart = interface(IInterface)
  Function getName: string;
  procedure setName(aValue: string)
  property Name: string read getName write setname;
end;


IOfferLine= interface(iInterface)
  Function getPart: IPart;
  function getAmount: double;
  procedure setPart(aPart: IPart);
  procedure setAmount(value: double);
  property Amount: double read getAmount write setAmount;
  property Part: IPart read GetPart write setPart;
end;

IOffer= interface(iInterface)
  function getOffLines: tList<IOfferline>;
  procedure setOffLines(aList: tList<IOfferline>);
  property OffLines: tList<IOfferlines> read getOffLines write setOfflines;
end;

现在我想实现这些界面。

TPart = class(TInterfacedObject, IPart)
  private
    _Name: string;
    function getName: string;
    procedure setName(aValue: string);
  public
    property Name: string read getName write setName;
end;

TOfferLine = class(TInterfacedObject, IOfferLine)
  private
    _amount: double;
    _part: TPart;
    function getAmount: double;
    function getPart: tPart;
    procedure setAmount(aValue: double);
    procedure setPart(aPart: TPart);
  public
    property Amount: double read getAmount write setAmount;
    property Part: TPart read GetPart write SetPart;
  end;

TOffer = class(TInterfacedObject, IOffer)
  private
    _OfferLines: tList<TOfferline>;
    function getOffLines: tList<tOfferline>;
    procedure setOffLines(aList: tList<tOfferline>);
  public
    property offLines: tList<TOfferline> read getOffLines write setOffLines;
end;

我添加了实现。

function TOfferLine.getPart: tPart;
begin
  result := _part;
end;

但我仍然得到&#39;缺少接口方法IOfferline.GetPart的实现;&#39;

我无法弄清楚原因。

2 个答案:

答案 0 :(得分:2)

我不知道你想要做什么,但是如果你没有把你的代码写得太乱,那么它就会更容易阅读。但感谢上帝,我们有一个Source格式化程序。

您的代码中存在seval问题:

First当您的界面名为property OffLines: TList<IOfferline**s**>

时,您的属性已声明为IOfferline

然后TOfferline你有一个方法procedure setPart(aPart: TPart);,它应该是procedure setPart(aPart:IPart);因为那就是你如何宣布你的界面。而使用TPart的所有其他地方都应该是IPart。

同样适用于TOffer

以下是代码的清理版本:

unit Unit20;

interface
uses
  Generics.Collections;

type
  IPart = interface(IInterface)
    function getName: string;
    procedure setName(aValue: string);
    property Name: string read getName write setName;
  end;

  IOfferLine = interface(IInterface)
    function getPart: IPart;
    function getAmount: double;
    procedure setPart(aPart: IPart);
    procedure setAmount(value: double);
    property Amount: double read getAmount write setAmount;
    property Part: IPart read getPart write setPart;
  end;

  IOffer = interface(IInterface)
    function getOffLines: TList<IOfferLine>;
    procedure setOffLines(aList: TList<IOfferLine>);
    property OffLines: TList < IOfferLine > read getOffLines write setOffLines;
  end;

  TPart = class(TInterfacedObject, IPart)
  private
    _Name: string;
    function getName: string;
    procedure setName(aValue: string);
  public
    property Name: string read getName write setName;
  end;

  TOfferline = class(TInterfacedObject, IOfferLine)
  private
    _amount: double;
    _part: TPart;
    function getAmount: double;
    function getPart: IPart;
    procedure setAmount(aValue: double);
    procedure setPart(aPart: IPart);
  public
    property Amount: double read getAmount write setAmount;
    property Part: IPart read getPart write setPart;
  end;

  TOffer = class(TInterfacedObject, IOffer)
  private
    _OfferLines: TList<TOfferline>;
    function getOffLines: TList<IOfferLine>;
    procedure setOffLines(aList: TList<IOfferLine>);
  public
    property OffLines: TList < IOfferLine > read getOffLines write setOffLines;
  end;

implementation

{ TOfferline }

function TOfferline.getAmount: double;
begin

end;

function TOfferline.getPart: IPart;
begin

end;

procedure TOfferline.setAmount(aValue: double);
begin

end;

procedure TOfferline.setPart(aPart: IPart);
begin

end;

{ TOffer }

function TOffer.getOffLines: TList<IOfferLine>;
begin

end;

procedure TOffer.setOffLines(aList: TList<IOfferLine>);
begin

end;

{ TPart }

function TPart.getName: string;
begin

end;

procedure TPart.setName(aValue: string);
begin

end;

end.

答案 1 :(得分:-1)

编译器说缺少实现的原因仅仅是因为缺少实现。

IOfferLine 的界面声明了此 getPart 方法:

IOfferLine= interface(iInterface)
  ..
  function getPart: IPart;
  ..
end;

但是你的实现类没有提供这种方法。您的类中的 getPart 方法实现为返回对象引用,而不是接口引用:

TOfferLine = class(TInterfacedObject, IOfferLine)
private
  ..
  function getPart: tPart;
  ..
end;

您需要确保您的实现类实际上准确而精确地提供了它所实现的接口所需的成员:

TOfferLine = class(TInterfacedObject, IOfferLine)
private
  ..
  function getPart: IPart;
  ..
end;

function TOfferline.getPart: IPart;
begin
  result := _part as IPart;
end;

但是,由于 OfferLine 对象(在 _part 变量中)对 Part 的引用是对象引用,因此引用使用接口获得的对象(通过 getPart:IPart 方法)可能导致 Part 对象被销毁,因为 OfferLine 中的对象引用是不计算(字面意思)。

您当然可以通过 OfferLine 保持部分引用本身来避免这种情况,但是这是否有效很难说完整的图片您的整个对象模型。如果你的对象的生命周期是由问题中没有明显的其他机制确定的那么它可能不是一个问题,但是如果它不是到目前为止特别考虑的东西那么它可能确实需要解决。

虽然可以安全地进行,但作为一般规则,混合对象引用和对相同对象的接口引用是一个问题的处方。