Home > Mobile >  How do I implement two methods from two interfaces with the same name?
How do I implement two methods from two interfaces with the same name?

Time:12-22

I'm having some trouble using method resolution clause in Delphi 10.4.

Say I want to create a cat and a dog repository. In this case the TAnimalRepository has both cats and dogs, so I would like to implement both the cat and dog interfaces in that class.

Example:

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;

Since we have two different methods with the same name, I have tried to use method resolution clause as described here: https://docwiki.embarcadero.com/RADStudio/Sydney/en/Implementing_Interfaces

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

But when I try to compile the above code, it fails with:

[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

Then I thought, why not try to add a method resolution for their inherited interface IRepositoryBase as well, like this:

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;

But now it gets funky. It looks like the compiler can't handle generics in the method resolution clause, because I get a lot of parsing errors now, beginning with:

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

It complains about this line:

function IRepositoryBase<TCat>.GetAll = GetAllCats;

What am I doing wrong? Do I really have to split my TAnimalRepository up in two different classes?

Thanks in advance.

Oh, one important note. I can get it to work, if my ICatRepository and IDogRepository doesn't inherit from IRepositoryBase. But in my use case, I would like them to inherit from the base class.

CodePudding user response:

You need to get rid of the additional declarations of GetAll in ICatRepository and IDogRepository. If you just leave the GUID in these interfaces all works as expected.

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;

The additional GetAll declarations don't just replace the generic one, but add another method to the interface instead.

  • Related