如何从具有相同名称的两个接口实现两个方法?

Posted

技术标签:

【中文标题】如何从具有相同名称的两个接口实现两个方法?【英文标题】:How do I implement two methods from two interfaces with the same name? 【发布时间】:2022-01-22 22:55:39 【问题描述】:

我在使用 Delphi 10.4 中的方法解析子句时遇到了一些问题。

假设我想创建一个猫和狗的存储库。在这种情况下,TAnimalRepository 既有猫又有狗,所以我想在该类中同时实现 cat 和 dog 接口。

例子:

IRepositoryBase<T> = Interface
    ['776B3383-AF6E-44F7-BF32-1ACCF9A6C964']
    function GetAll(items: TList<T>; out errMsg: String): Boolean;
End;

TCat = class
end;

ICatRepository = Interface(IRepositoryBase<TCat>)
    ['C37CF989-E069-450B-8937-E46F6BFA66E9']
    function GetAll(items: TList<TCat>; out errMsg: String): Boolean;
End;

TDog = class
end;

IDogRepository = Interface(IRepositoryBase<TDog>)
    ['56B28463-0007-497E-8015-D794873328FF']
    function GetAll(items: TList<TDog>; out errMsg: String): Boolean;
End;

TAnimalRepository = class(TInterfacedObject, ICatRepository, IDogRepository)
    function ICatRepository.GetAll = GetAllCats;
    function IDogRepository.GetAll = GetAllDogs;
public
    function GetAllCats(items: TList<TCat>; out errMsg: String): Boolean;
    function GetAllDogs(items: TList<TDog>; out errMsg: String): Boolean;
end;

由于我们有两个同名的不同方法,我尝试使用这里描述的方法解析子句: https://docwiki.embarcadero.com/RADStudio/Sydney/en/Implementing_Interfaces

function ICatRepository.GetAll = GetAllCats;
function IDogRepository.GetAll = GetAllDogs;

但是当我尝试编译上面的代码时,它失败了:

[dcc32 Error] MethodResolutionExample.dpr(33): E2291 Missing implementation of interface method MethodResolutionExample.IRepositoryBase<MethodResolutionExample.TDog>.GetAll

[dcc32 Error] MethodResolutionExample.dpr(33): E2291 Missing implementation of interface method MethodResolutionExample.IRepositoryBase<MethodResolutionExample.TCat>.GetAll

然后我想,为什么不尝试为他们继承的接口 IRepositoryBase 添加一个方法解析,就像这样:

TAnimalRepository = class(TInterfacedObject, ICatRepository, IDogRepository)
    function ICatRepository.GetAll = GetAllCats;
    function IRepositoryBase<TCat>.GetAll = GetAllCats;  // <--- This
    function IDogRepository.GetAll = GetAllDogs;
    function IRepositoryBase<TDog>.GetAll = GetAllDogs;  // <--- This
public
    function GetAllCats(items: TList<TCat>; out errMsg: String): Boolean;
    function GetAllDogs(items: TList<TDog>; out errMsg: String): Boolean;
end;

但现在它变得很时髦。看起来编译器无法处理方法解析子句中的泛型,因为我现在遇到很多解析错误,首先是:

[dcc32 Error] MethodResolutionExample.dpr(35): E2023 Function needs result type

它抱怨这条线:

function IRepositoryBase<TCat>.GetAll = GetAllCats;

我做错了什么?我真的必须将我的 TAnimalRepository 分成两个不同的类吗?

提前致谢。

哦,重要的一点。如果我的 ICatRepository 和 IDogRepository 没有从 IRepositoryBase 继承,我可以让它工作。但在我的用例中,我希望它们从基类继承。

【问题讨论】:

【参考方案1】:

您需要去掉 ICatRepositoryIDogRepository 中的 GetAll 的附加声明。如果您只是将 GUID 留在这些界面中,那么一切都会按预期工作。

type
  IRepositoryBase<T> = interface
    ['776B3383-AF6E-44F7-BF32-1ACCF9A6C964']
    function GetAll(items: TList<T>; out errMsg: string): Boolean;
  end;

  TCat = class
  end;

  ICatRepository = interface(IRepositoryBase<TCat>)
    ['C37CF989-E069-450B-8937-E46F6BFA66E9']
  end;

  TDog = class
  end;

  IDogRepository = interface(IRepositoryBase<TDog>)
    ['56B28463-0007-497E-8015-D794873328FF']
  end;

  TAnimalRepository = class(TInterfacedObject, ICatRepository, IDogRepository)
    function ICatRepository.GetAll = GetAllCats;
    function IDogRepository.GetAll = GetAllDogs;
  public
    function GetAllCats(items: TList<TCat>; out errMsg: string): Boolean;
    function GetAllDogs(items: TList<TDog>; out errMsg: string): Boolean;
  end;

额外的 GetAll 声明不只是替换通用声明,而是向接口添加另一种方法。

【讨论】:

谢谢!这就说得通了。我不知道为什么我首先在​​ cat 和 dog 存储库中添加了 GetAll 函数。

以上是关于如何从具有相同名称的两个接口实现两个方法?的主要内容,如果未能解决你的问题,请参考以下文章

用相同的方法在一个类中实现两个接口。哪个接口方法被覆盖?

c#中如何在一个类里实现两个接口里的方法名称一样的两个方法

C# 多接口继承不允许具有相同名称的公共访问修饰符

为啥继承具有名称签名的接口成员的 C# 抽象类至少需要实现其中一个?

C# 等效于 VB.NET 接口实现

如何实现具有公共属性但私有设置方法的多个接口?