我知道标题非常广泛 - 跨越很多!
我希望这个问题可能演变成一个更大的“信息wiki thingy”。
我所学到的知识 - 到目前为止:
(请纠正我 - 如果你认为我错了,遗失或误解了什么)。
我的问题是:
但到现在为止,我已经花了无数个小时,试图弄明白,如何解决我在桌面上的这个“大难题”。而且我已经从你们这些SO用户那里得到了一些很好的答案 - 但是现在是时候让他们有更大规模的工作了。
我用这个冒险进入泛型: Generics and Polymorphism working together
现在我有点坚持这个: Situations where Generics won't work
为什么我最终会出现协方差问题 - 是因为我的层次结构中的类程序。
所以我想知道Interfaces是否是我在这个“传奇”中的下一个大胆举动。 如何“跨越”协方差问题。 有一件事是要发现你确实遇到了这个问题 - 另一件事就是“如何解决它”。
因此,如果你们中的任何一个好人“在那里”对此有任何意见 - 我全都听见了。 基本上: 告诉我去接口(我从来没有从头开始做过)。 或者......按照你建议的方向向我扔骨头。
我当前的源池如第二个链接所述 - 从顶部开始。
这是我之前post的一小段代码,显示了我的协方差问题。 David善意地解释了 - 为什么我遇到灌木丛......但现在我需要了解 - 如何绕过它。
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;
此致
答案 0 :(得分:5)
你无法做你想做的事,但这不是你如何使用泛型。正如Rob Kennedy所说,拥有TCustomerList<TCustomer>
和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);
也许您可能必须指定T
(某些早期版本的泛型不处理类型推断 - 即它从参数类型中推断出T
的类型 - 非常好) ,即
ProcessList<TCustomer>(aCustomerList);
ProcessList<TPerson>(aPersonList);
但是,或者类似的东西,你应该做的。 IMO,其他任何事情都没有意义。没有必要拥有一个可以容纳任何这些列表的变量,例如aList
。如果你真的需要一个,你只能使用TObject
,但这不允许你以任何有用的方式使用列表。它不是很通用。
接口对这个问题根本无济于事。您可以通过接口(另一种多态)为类提供某些功能,即列表元素。但这不会处理协方差。
答案 1 :(得分:0)
我会选择:
TCustomCustomerList = class(TBaseList<TBaseObject>)
end;
TCustomerList = class(TCustomCustomerList)
end;
在您的设计中这是否可以接受是完全不同的事情。如果您要实现的目标是将TCustomerList分配给TBaseList变量,那么这将是最佳选择。