Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 使用泛型接口的错误重载调用_Delphi_Delphi Xe2 - Fatal编程技术网

Delphi 使用泛型接口的错误重载调用

Delphi 使用泛型接口的错误重载调用,delphi,delphi-xe2,Delphi,Delphi Xe2,假设我有这样的定义: TMyClass1 = class end; TMyClass2 = class end; IModel<T : class> = interface ['{E8262D6C-DCAB-46AC-822E-EC369CF734F8}'] function List() : TObjectList<T>; end; IPresenter<T : class> = interface ['{98FB7751-D75A-4C5

假设我有这样的定义:

TMyClass1 = class
end;

TMyClass2 = class
end;

IModel<T : class> = interface
  ['{E8262D6C-DCAB-46AC-822E-EC369CF734F8}']
  function List() : TObjectList<T>;
end;

IPresenter<T : class> = interface
  ['{98FB7751-D75A-4C51-B55A-0E5FE68BE213}']
  function Retrieve() : TObjectList<T>;
end;

IView<T : class> = interface
  ['{59384CD6-30D6-4BD8-AB3D-7FCF4D1A8618}']
  procedure AssignPresenter(APresenter : IPresenter<T>);
end;

TModel<T : class> = class(TInterfacedObject, IModel<T>)
public
  function List() : TObjectList<T>; virtual; abstract;
end;

TPresenter<T : class> = class(TInterfacedObject, IPresenter<T>)
strict private
  { Private declarations }
  FModel : IModel<T>;
  FView : IView<T>;
public
  constructor Create(AView : IView<T>);
  function Retrieve() : TObjectList<T>; virtual; abstract;
end;

TModelClass1 = class(TModel<TMyClass1>);

TPresenterClass1 = class(TPresenter<TMyClass1>);

TModelClass2 = class(TModel<TMyClass2>);

TPresenterClass2 = class(TPresenter<TMyClass2>);
TMyClass1=class
结束;
TMyClass2=类
结束;
IModel=接口
['{E8262D6C-DCAB-46AC-822E-EC369CF734F8}']
函数列表():TObjectList;
结束;
IPresenter=接口
[{98FB7751-D75A-4C51-B55A-0E5FE68BE213}]
函数Retrieve():TObjectList;
结束;
IView=接口
[{59384CD6-30D6-4BD8-AB3D-7FCF4D1A8618}]
程序分配提交人(中间人:I提交人);
结束;
TModel=class(TInterfacedObject,IModel)
公众的
函数列表():TObjectList;事实上的摘要
结束;
TPresenter=class(TInterfacedObject,IPresenter)
严格保密
{私有声明}
f模型:IModel;
FView:IView;
公众的
构造函数创建(AView:IView);
函数Retrieve():TObjectList;事实上的摘要
结束;
TModelClass1=类(TModel);
tpresenterclass=class(TPresenter);
TModelClass2=类(TModel);
TPresenterClass2=类(TPresenter);
我有一个表单,它实现了我定义的一些东西:

TForm1 = class(TForm, IView<TMyClass1>, IView<TMyClass2>)
  procedure FormCreate(Sender: TObject);
private
  { Private declarations }
  FPresenter1 : IPresenter<TMyClass1>;
  FPresenter2 : IPresenter<TMyClass2>;
  procedure AssignPresenter(APresenter : IPresenter<TMyClass1>); overload;
  procedure AssignPresenter(APresenter : IPresenter<TMyClass2>); overload;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 TPresenterClass1.Create((Self as IView<TMyClass1>));
 TPresenterClass2.Create((Self as IView<TMyClass2>));
end;

procedure TForm1.AssignPresenter(APresenter: IPresenter<TMyClass1>);
begin
  Self.FPresenter1 := APresenter;
end;

procedure TForm1.AssignPresenter(APresenter: IPresenter<TMyClass2>);
begin
  Self.FPresenter2 := APresenter;
end;
TForm1=class(TForm,IView,IView)
过程表单创建(发送方:ToObject);
私有的
{私有声明}
FPresenter1:IPresenter;
FPresenter2:IPresenter;
程序分配提交人(中间人:I提交人);超载;
程序分配提交人(中间人:I提交人);超载;
结束;
过程TForm1.FormCreate(发送方:TObject);
开始
tpresenterclas1.Create((作为IView的自我));
TPresenterClass2.Create((Self as IView));
结束;
程序TForm1.指定演示者(一个演示者:I演示者);
开始
Self.FPresenter1:=APresenter;
结束;
程序TForm1.指定演示者(一个演示者:I演示者);
开始
Self.FPresenter2:=APresenter;
结束;
所以这里的问题是delphi无法确定要调用什么方法,在本例中,在这两种情况下都只调用
AssignPresenter(APresenter:IPresenter)
,因此我可能在这里遗漏了一些东西,但我无法理解atm


提前谢谢。

这可能是重复的,但我现在找不到

问题是接口的
as
运算符与泛型不太兼容。
as
运算符依赖于接口GUID。通过查询具有匹配GUID的接口可以找到该接口。而且guid根本不适合泛型实例化

现在让我们看看您的代码

TPresenterClass1.Create((Self as IView<TMyClass1>));
TPresenterClass2.Create((Self as IView<TMyClass2>));
tpresenterclas1.Create((作为IView的自我));
TPresenterClass2.Create((Self as IView));
问题在于
IView
IView
具有相同的GUID:

type
  IView<T : class> = interface
    ['{59384CD6-30D6-4BD8-AB3D-7FCF4D1A8618}']
    procedure AssignPresenter(APresenter : IPresenter<T>);
  end;
类型
IView=接口
[{59384CD6-30D6-4BD8-AB3D-7FCF4D1A8618}]
程序分配提交人(中间人:I提交人);
结束;
因此
IView
IView
共享相同的GUID,当您使用
as
进行查询时,无论您是否请求
IView
IView
,都将返回相同的界面

因此,这里的底线是,只要一个对象用不同的
T
实现了
isomointerface
两次,那么
as
在通用接口中几乎是无用的

Embarcadero确实应该以支持泛型的方式实现
as
。但我不会让你屏住呼吸


你需要找到一种不同的方法来解决你的问题。

作为大卫·赫弗南答案的补充

解决此问题的一种方法是为您使用的所有通用声明提供唯一的GUID:

IViewMyclass1 = interface(IView<TMyClass1>)
['{1A0F941F-BAB1-4723-A6C1-27036DF5D344}']
end;

IViewMyclass2 = interface(IView<TMyClass2>)
['{0C61A23A-DC50-43B0-97C9-8B0013DDC193}']
end;
然后调用正确的重载

免责声明:

  • 这是动态测试(XE4)的结果。可靠性是未知的
  • 我知道这不太实际
  • 它可能不应该被广泛使用,因为代码失败的地方并不明显

当对象实现接口时,无需将
用作
,只需编写:

procedure TForm1.FormCreate(Sender: TObject);
begin
  TPresenterClass1.Create(Self);
  TPresenterClass2.Create(Self);
end;

编译器正确地解决了这个问题。当您将
用作
时,它会执行一个
支持的
调用,由于David已经解释过的原因,该调用失败。

@EProgrammer我找到了一个,但有点不同。这是关于没有GUID的问题。这是关于泛型实例化和guid的。
procedure TForm1.FormCreate(Sender: TObject);
begin
  TPresenterClass1.Create(Self);
  TPresenterClass2.Create(Self);
end;