使用接口强制实现接口返回类型吗?

时间:2011-10-21 12:00:23

标签: delphi interface

使用接口时,实现类方法是强制返回接口,还是有办法返回对象?

一个例子将澄清:

单位EmployeeIntf中的

IEmployee = interface(IInterface)
  function CoWorker: IEmployee; // We dont know anything about TEmployee here
end;
单位员工

uses EmployeeIntf;
...

TEmployee = class(TObject, IEmployee)
public
  function CoWorker: IEmployee; // Returns an error if set to TEmployee
end;

如果方法返回TEmployee,则当前代码在编译器错误时停止:E2211“CoWorker”声明与接口IEmployee中的声明不同(使用Delphi 2010)

TEmployee.CoWorker方法是强制返回接口,还是有办法返回TEmployee,只要TEmployee是IEmployee?

如果在这种情况下只允许接口,那么OO设计的原因是什么?

[编辑]

  • 正如许多贡献者所要求的,我不需要重新计算TEmployee,并希望将上述问题与任何重新计算的考虑因素区分开来。

  • 这个问题的背景是需要在外部组件(在单独的包中)中使用TEmployee的一组非常有限的公共函数。我不能简单地导入包中的'Employee'单元,因为在使用部分中有太多不依赖的依赖项,所以我正在寻找一种松散耦合的解决方案。

谢谢,

5 个答案:

答案 0 :(得分:3)

  

是强制返回接口的实现类方法吗?

不,但实施被强制匹配接口定义的签名。

  

有办法返回对象吗?

是的,如果您相应地声明了界面。

type
  IEmployee = interface
    function CoWorker: TEmployee;
  end;

答案 1 :(得分:3)

您可以通过引入方法解析子句来使编译器满意:

type
  TEmployee = class(TInterfacedObject, IEmployee)
    function IEmployee.CoWorker = IEmployeeCoWorker;
  public
    function IEmployeeCoWorker: IEmployee;
    function CoWorker: TEmployee;
  end;

function TEmployee.IEmployeeCoWorker: IEmployee;
begin
  result := CoWorker;
end;

当然,这会使代码复杂化,但如果它实际上是你需要的......

答案 2 :(得分:2)

我假设您希望CoWorker函数返回IEmployee,以便为此接口的客户端带来好处。

但是,某些时候实现代码有一个访问实现对象的正当理由。当然这样做会产生一种可能不合需要的耦合。

从Delphi 2010开始,您可以使用as运算符来访问实现对象。

var
  EmpIntf: IEmployee;
  EmpImp: TEmployee;
...
  EmpImp := EmpIntf as TEmployee;

请注意,您现在正在破坏对象的生命周期管理。如果在界面引用变为零后访问EmpImp,则表示您遇到了麻烦。

最后,我会评论说使用这种方法会有糟糕的设计风格。通常以这种方式找到不是as的方法更好。

答案 3 :(得分:1)

Delphi不支持covariant return types.所以这与接口无关,而只是对语言本身的限制。

通常这不是问题,因为客户通常应该使用IEmployee而不应该关心同事的具体类型。您必须提供更多详细信息(可能在新问题中),为什么需要特定类型。

如果你使用接口引用计数,你有更多的理由只使用接口类型引用,因为混合接口和对象引用会搞乱引用计数。

答案 4 :(得分:1)

如果要定义一个返回接口的接口函数,为什么要在实现中返回一个对象?

我相信你只是不知道如何实现“功能CoWorker:IEmployee”。如果这是问题,这是一个简单的解决方案:

TEmployee = class(TInterfacedObject, IEmployee)
public
  function CoWorker: IEmployee;
end;

function TEmployee.CoWorker: IEmployee;
begin
  Result := TEmployee.Create;
end;

顺便说一下,你应该从TInterfacedObject派生接口实现对象,而不是从TObject派生。

[编辑]

至于你的澄清 - 你不能为TEmployee定义一个小的公共接口,然后从这两个接口派生这个类吗?像这样:

type
  IEmployeePublic = ...
  IEmployee = ...

  TEmployee = class(TInterfacedObject, IEmployee, IEmployeePublic)
    function CoWorker: IEmployeePublic;
  end;