【发布时间】:2022-01-03 10:32:21
【问题描述】:
我有一个实现多个版本的通用接口的对象。为避免混淆,我在课堂上使用方法解析子句: https://docwiki.embarcadero.com/RADStudio/Sydney/en/Implementing_Interfaces
假设我有一个多动物处理程序,可以处理猫和狗(不管是什么意思)。处理程序为猫和狗实现了处理程序 (IRequestHandler<TResponse, TRequest>) 接口:
IRequestHandler<TResponse: record; TRequest: record> = Interface(IInvokable)
['{AFF8703B-F2AC-44D6-B82C-43E3492ADBB3}']
function Handle(ARequest: TRequest): TResponse;
End;
TCatRequest = record
end;
TCatResponse = record
end;
TDogRequest = record
end;
TDogResponse = record
end;
TMultiAnimalHandler=class(TInterfacedObject,
IRequestHandler<TCatResponse, TCatRequest>,
IRequestHandler<TDogResponse, TDogRequest>)
public
function IRequestHandler<TCatResponse, TCatRequest>.Handle = HandleCatRequest;
function HandleCatRequest(ARequest: TCatRequest): TCatResponse;
function IRequestHandler<TDogResponse, TDogRequest>.Handle = HandleDogRequest;
function HandleDogRequest(ARequest: TDogRequest): TDogResponse;
end;
问题是,当我尝试对特定接口 IRequestHandler<TCatResponse, TCatRequest> 和 IRequestHandler<TDogResponse, TDogRequest> 进行类型转换时,它并不总是解析为正确的方法。
完整示例:
type
IRequestHandler<TResponse: record; TRequest: record> = Interface(IInvokable)
['{AFF8703B-F2AC-44D6-B82C-43E3492ADBB3}']
function Handle(ARequest: TRequest): TResponse;
End;
TCatRequest = record
end;
TCatResponse = record
end;
TDogRequest = record
end;
TDogResponse = record
end;
TMultiAnimalHandler=class(TInterfacedObject,
IRequestHandler<TCatResponse, TCatRequest>,
IRequestHandler<TDogResponse, TDogRequest>)
public
function IRequestHandler<TCatResponse, TCatRequest>.Handle = HandleCatRequest;
function HandleCatRequest(ARequest: TCatRequest): TCatResponse;
function IRequestHandler<TDogResponse, TDogRequest>.Handle = HandleDogRequest;
function HandleDogRequest(ARequest: TDogRequest): TDogResponse;
end;
function TMultiAnimalHandler.HandleCatRequest(
ARequest: TCatRequest): TCatResponse;
begin
WriteLn('Miav!');
end;
function TMultiAnimalHandler.HandleDogRequest(
ARequest: TDogRequest): TDogResponse;
begin
WriteLn('Woof!');
end;
var
catHandler: IRequestHandler<TCatResponse, TCatRequest>;
dogHandler: IRequestHandler<TDogResponse, TDogRequest>;
multiAnimalHandler: TMultiAnimalHandler;
dogRequest: TDogRequest;
catRequest: TCatRequest;
begin
try
multiAnimalHandler := TMultiAnimalHandler.Create;
dogHandler := multiAnimalHandler;
catHandler := multiAnimalHandler;
// Works
dogHandler.Handle(dogRequest);
// Works
catHandler.Handle(catRequest);
// Works
(multiAnimalHandler as IRequestHandler<TDogResponse, TDogRequest>).Handle(dogRequest);
// Does not work. The Handle function calls HandleDogRequest, even if I cast multiAnimalHandler to IRequestHandler<TCatResponse, TCatRequest>!?
(multiAnimalHandler as IRequestHandler<TCatResponse, TCatRequest>).Handle(catRequest);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
令人不安的是:
(multiAnimalHandler as IRequestHandler<TCatResponse, TCatRequest>).Handle(catRequest);
代码将调用HandleDogRequest而不是HandleCatRequest,这是我预期的。
上面的代码会产生如下输出:
Woof!
Miav!
Woof!
Woof!
我做错了什么或错过了什么?
谢谢!
编辑:解决方法
在我的特定用例中,我可以将我的对象类型转换为具体的实现。没有那么漂亮的代码,但它可以工作。
IRequestHandler<TCatResponse, TCatRequest>(invokable).Handle(catRequest)
【问题讨论】: