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.