泛型,多态,接口:解决方案是什么?

Bim*_*r_R 6 delphi generics polymorphism covariance delphi-xe2

我知道标题非常广泛 - 跨越很多!

而且我希望这个问题可能演变成一个更大的"信息wiki thingy".

我学到了什么 - 到目前为止:

  • 使用泛型时 - 理解概念(协方差和逆变).
  • 不要"误用"泛型与继承相结合的概念.我做了,它可以让你直接陷入协方差问题!确保在继承中的正确位置"中断"泛型 - 如果要将两者结合起来.

(请纠正我 - 如果你认为我错了,错过或误解了什么).

我的问题是:

但到现在为止,我花了无数个小时,想弄清楚,如何解决我在桌面上的这个"大难题".而且我已经从你们这些SO用户那里得到了一些很好的答案 - 但是现在是时候让更大规模的工作了.

我冒昧地使用这个: Generics和Polymorphism一起工作

现在我有点困在这一点: 泛型不起作用的情况

为什么我最终得到协方差问题 - 是因为我的层次结构中的类过程.

所以我想知道Interfaces是否是我在这个"传奇"中的下一个大胆举动.如何"跨越"协方差问题.有一件事是发现你确实遇到了这个问题 - 另一件事是"如何解决它".

因此,如果你们中的任何一个好人"在那里"对此有任何意见 - 我都是耳朵.基本上:告诉我去接口(我从来没有从头开始做过).或者......按照你建议的方向给我一块骨头.

我当前的源池如第二个链接所述 - 从顶部开始.

这是我之前发布的一个小片段,显示了我的协方差问题. 大卫好心地解释了 - 为什么我跑进灌木丛......但现在我需要信息 - 如何绕过它.

var    
  aList : TBaseList<TBaseObject>;  // used as a list parameter for methods
  aPersonList : TPersonList<TPerson>;
  aCustomerList : TCustomerList<TCustomer>;
begin
  aPersonList := TPersonList<TPerson>.Create;
  aCustomerList := TCustomerList<TCustomer>.Create;

  aList := aCustomerList;  <-- this FAILS !!  types not equal ..

end;
Run Code Online (Sandbox Code Playgroud)

问候

Rud*_*uis 5

你无法做你想做的事,但这并不是你如何使用泛型.正如Rob Kennedy所说,拥有a TCustomerList<TCustomer>和a 是没有意义的TPersonList<TPerson>.泛型的美妙之处在于您可以对不同的元素类型使用相同的列表.这意味着列表和元素类型不得具有任何依赖关系.

你可以这样做:

procedure TSomething.ProcessList<T: TBaseObject>(const aList: TBaseList<T>);
begin
  // process the list using code that is independent of the actual type of T.
end;

...

var
  aCustomerList: TBaseList<TCustomer>;
  aPersonList: TBaseList<TPerson>;
begin
  ProcessList(aCustomerList);
  ProcessList(aPersonList);
Run Code Online (Sandbox Code Playgroud)

也许你可能需要指定T(仿制药没有处理类型推断的一些早期版本-即它inferes的类型T从参数的类型-非常好),即

  ProcessList<TCustomer>(aCustomerList);
  ProcessList<TPerson>(aPersonList);
Run Code Online (Sandbox Code Playgroud)

但那或类似的东西是你应该做的.IMO,其他任何事情都没有意义.没有必要有一个可以保存这些列表的变量,比如你的aList.如果你真的需要一个,你只能使用TObject,但这不允许你以任何有用的方式使用列表.它不是很通用.

接口对这个问题根本无济于事.您可以通过接口(另一种多态)为类提供某些功能,即列表元素.但这不会处理协方差.