Delphi 泛型、多态性、接口:解决方案是什么?

Delphi 泛型、多态性、接口:解决方案是什么?,delphi,generics,polymorphism,delphi-xe2,covariance,Delphi,Generics,Polymorphism,Delphi Xe2,Covariance,我知道这个标题是非常广泛的-跨越了很多 我希望这个问题可能会演变成一个关于这些主题的更大的“信息维基” 我所学到的-到目前为止: 使用泛型时-理解概念() 泛型与继承相结合的概念。我做到了,这会让你直接陷入协方差问题!确保在继承中的正确位置“断开”泛型-如果要将两者结合起来 (如果你认为我错了、遗漏了或误解了什么,请纠正我) 我的问题是: 但到现在为止,我已经花了无数个小时,试图弄明白如何解决我桌上的这个“大难题”。我已经从你们中的一些人那里得到了一些很好的答案,所以已经有很多用户了——但现

我知道这个标题是非常广泛的-跨越了很多

我希望这个问题可能会演变成一个关于这些主题的更大的“信息维基”

我所学到的-到目前为止:

  • 使用泛型时-理解概念()
  • 泛型与继承相结合的概念。我做到了,这会让你直接陷入协方差问题!确保在继承中的正确位置“断开”泛型-如果要将两者结合起来
(如果你认为我错了、遗漏了或误解了什么,请纠正我)

我的问题是:

但到现在为止,我已经花了无数个小时,试图弄明白如何解决我桌上的这个“大难题”。我已经从你们中的一些人那里得到了一些很好的答案,所以已经有很多用户了——但现在是时候让一些东西在更大范围内发挥作用了

我用这本书冒险研究了泛型:

现在我有点被困在这个问题上:

为什么我最终会遇到协方差问题——是因为我的层次结构中的类过程

所以我想知道接口是否是我在这个“传奇”中的下一个大胆举动。 如何“跨越”协方差问题。 一件事是发现你确实有这个问题——另一件事是“如何解决它”

所以,如果你们这些“外面”的好人对这件事有什么意见,我洗耳恭听。 基本上: 告诉我选择接口(我自己从来没有从头做过一个)。 或向你建议的方向扔根骨头给我

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

下面是我之前的一个小片段,它显示了我的协方差问题。 好心的解释-为什么我会撞到灌木丛。。但现在我需要关于如何绕过它的信息

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;
var
列表:TBaseList;//用作方法的列表参数
人员列表:TPersonList;
aCustomerList:t客户列表;
开始
aPersonList:=TPersonList.Create;
aCustomerList:=tccustomerlist.Create;
aList:=aCustomerList 我会选择:

TCustomCustomerList = class(TBaseList<TBaseObject>)
end;

TCustomerList = class(TCustomCustomerList)
end;
TCustomCustomerList=class(TBaseList)
结束;
TCustomerList=类(TCustomCustomerList)
结束;

这在您的设计中是否可以接受是一个完全不同的问题。如果您试图实现的目标是将TCustomerList分配给TBaseList变量,那将是一种方法。

您不能做您想做的事情,但无论如何,这不是您使用泛型的方式。正如Rob Kennedy所说,拥有
t客户列表
t个人列表
是没有意义的。泛型的美妙之处在于,您可以对不同的元素类型使用相同的列表。这意味着列表和元素类型不能有任何依赖关系

您可以执行以下操作:

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);
但这,或类似的事情,是你应该做的。其他任何东西都没有意义,IMO。不需要一个变量来保存这些列表中的任何一个,比如你的
aList
。如果您真的需要,您只能使用
TObject
,但这不允许您以任何有用的方式使用列表。而且它不是很通用


接口根本帮不了你解决这个问题。您可以通过接口(另一种多态性)为类提供某些功能,也就是列表的元素。但这不能处理协方差。

如果我们真的知道你的实际问题是什么,这会有所帮助。根据我的经验,如果设计不太复杂,协方差很少是个问题。瞧,告诉我们真正的问题,这样我们就有具体的问题要解决。@RudyVelthuis好吧。。。正如您所提到的,它非常复杂,需要对前一个进行大量重写。但基本上是同一个问题——只是问题变了。既然我现在知道我做错了什么——我只希望有人能为我指明解决问题的方向。如果仍然不清楚,请告诉我,我会尽力解释。如何解决这个问题取决于问题是什么。一旦给
aList
赋值,您希望如何处理该变量?(还有,为什么TPersonList和TCustomerList是泛型的?你还可以拥有什么样的TPersonList?)在我的第一篇文章中,我提出了一个解决方案,在我的TBaseList中,我只有很少的代码行。Marshal方法可以封送/序列化OOP层次结构中的任何列表。返回时,泛型再次用于解组。我必须为每个子类指定的全部内容是自定义转换器和还原器。这并不是我能拥有的TPersonList,而是我拥有TBaseList.FWIW的90个子类,泛型是多态性的一种形式。多态性的种类比遗传多态性更多。通常,你只使用其中一个,而不是同时使用两个,尽管你可以。所以你建议我应该打破基本定义之上的通用链。。。六羟甲基三聚氰胺六甲醚。。。我会尝试一个测试项目,然后再给你回复。可能需要几个小时我才能回复你。正如你所看到的,我目前正在测试。。。到目前为止,我似乎同意鲁迪的建议(基本上与你的建议相同,但解释得更详细)。+1类型推断意味着你应该能够将它写成
ProcessList(aCustomerList)
ProcessList(aPersonList)
@David:我知道,但类型推断并不总是像预期的那样工作,尤其是在支持泛型的早期版本中。请注意,我确实编写了ProcessList(等等),但有一条但书规定,这种方式可能不被接受。“也许您必须指定”有点含糊不清。我想这就是让我困惑的地方。你最好说简洁的语法应该有用,但是编译器的一些版本不喜欢它。奇怪的是,我最近发现了一个与此相反的泛型错误。类型推断语法起作用,替代方法产生内部错误。@RudyVelthuis。这看起来
  ProcessList<TCustomer>(aCustomerList);
  ProcessList<TPerson>(aPersonList);