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);