DELPHI:泛型和多态性

前端之家收集整理的这篇文章主要介绍了DELPHI:泛型和多态性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
已经有几种不同的方法被问到了 – 但是我还没有找到我的答案.

有人可以为我解释一些事情吗
使用:Delphi XE2

我有一个相当大的BaSEObject,我几乎用于所有的东西.
随着它我有一个通用列表 – BaseList.

声明如下:

TBaSEObject = class
... a lot of properties and methods ...
end;

TBaseList<T: TBaSEObject> = class(TObjectList<T>)
... some properties and methods ... 
end;

我最近尝试从一个非常旧的TStringList使用Objects []属性…更改TBaseList声明到这个从未更通用的泛型列表TObjectList.

但我遇到一些问题.
BaseUnit是一个文件…每次我下载我的BaSEObject我也做一个专门的列表来跟踪它.

所以我会去做一些像:

TCustomer = class(TBaSEObject)
... customer related stuff ...
end;

TCustomerList<T: TCustomer> = class(TBaseList<T>)
... customer list specific stuff ...
end;

但是现在我想要一个对象包含一个可以容纳任何对象的列表.
我以为我可以这样做

TControlObject = class(TBaSEObject)
  FGenList: TBaseList<TBaSEObject>; 
end;

由于BaseList和BaSEObject是我的层次结构的顶层,所以我认为这样一个List可以容纳任何可以想到的列表.

但我有一种感觉,在这里我失败了…
TBaseList< TBaSEObject>在某种程度上与TCustomerList< TCustomer>不相似…
即使TCustomerList和TCustomer都是从我的基础下降的.

我希望能够在baselist中使用仿制药来镇压新物体.
即.在填充方法中使用T.Create.

以下是完整层次结构的示例:

Base Unit;
TBaSEObject = class
end;
TBaseList<T:TBaSEObject> = class(TObjectList<T>)
end;

CustomCustomer Unit;
TCustomCustomer = class(TBaSEObject) 
end;
TCustomCustomerList<T:TCustomCustomer> = class(TBaseList<T>)
end;

Customer Unit;
TCustomer = class(TCustomCustomer)
end;
TCustomerList<T:TCustomer> = class(TCustomCustomerList<T>)
end;

CustomPerson Unit;
TCustomPerson = class(TBaSEObject) 
end;
TCustomPersonList<T:TCustomPerson> = class(TBaseList<T>)
end;

Person Unit;
TPerson = class(TCustomPerson)
end;
TPersonList<T:TPerson> = class(TCustomPersonList<T>)
end;

鉴于上述层次结构 – 为什么我不能:

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;

调用处理所有列表的基类的过程失败相同的方式…

Procedure LogStuff(SomeList : TBaseList<TBaSEObject>)
begin
  writeln(Format( 'No. Elements in list : %d',[SomeList.Count]));
end;

有人可以打我,告诉我我在这里做错了吗?

解决方法

Delphi泛型不支持协方差和逆向,所以您尝试做的是不可能使用语言的当前语法.我建议您阅读以下博客文章,更详细地介绍这个问题.

> Craig Stuntz: Comparing C#,C++,and Delphi (Win32) Generics
> Mason Wheeler: Generics and the Covariance Problem

从根本上说,你试图做的是这样的:

type
  TBase = class;
  TDerived = class(TBase);
  TBaseList = TList<TBase>;
  TDerivedList = TList<TDerived>;
var
  BaseList: TBaseList;
  DerivedList: TDerivedList;
...
BaseList := TDerivedList;//does not compile

设计师没有阻止你这样做.有一个很好的理由考虑以下标准示例:

type
  TAnimal = class;
  TCat = class(TAnimal);
  TPenguin = class(TAnimal);

var
  AnimalList: TList<TAnimal>;
  CatList: TList<TCat>;
  Penguin: TPenguin;
...
AnimalList := CatList;//does not compile because...
AnimalList.Add(Penguin);//...of the danger of this

尽管向TList< TAnimal>添加TPenguin是合理的,但是AnimalList引用的实际列表是TList< TCat>企鹅不是一只猫.

而且,如果你想在你的示例层次结构的上下文中考虑它,这里是一个证明语言设计的代码的例证.

aList := aCustomerList;//does not compile
aList.Add(aCustomPerson);
//this would add a TCustomPerson instance to a list containing 
//TCustomer instances,but a TCustomPerson is not a TCustomer

猜你在找的Delphi相关文章