我的代码有问题,它使用泛型类型.为什么编译器不知道传递的列表(Result)是TObjectList< TItem> (TItem是TItems中T的类型)?
接口:
type TItem = class end; type IItemsLoader = interface procedure LoadAll(AList : TObjectList<TItem>); end; type TItemsLoader = class(TInterfacedObject,IItemsLoader) public procedure LoadAll(AList : TObjectList<TItem>); end; type IItems<T : TItem> = interface function LoadAll : TObjectList<T>; end; type TItems<T : TItem> = class(TInterfacedObject,IItems<T>) private FItemsLoader : TItemsLoader; public constructor Create; destructor Destroy; override; function LoadAll : TObjectList<T>; end;
执行:
procedure TItemsLoader.LoadAll(AList: TObjectList<TItem>); begin /// some stuff with AList end; { TItems<T> } constructor TItems<T>.Create; begin FItemsLoader := TItemsLoader.Create; end; destructor TItems<T>.Destroy; begin FItemsLoader.Free; inherited; end; function TItems<T>.LoadAll: TObjectList<T>; begin Result := TObjectList<T>.Create(); /// Error here /// FItemsLoader.LoadAll(Result); end;
解决方法
在带错误的函数中,Result是TObjectList< T>,其中T是TItem的某个子类,但编译器不知道它是什么特定的类.编译器必须对其进行编译,以便可以安全地运行任何T值.这可能与LoadAll的参数类型不兼容,后者需要TObjectList< TItem>,因此编译器会拒绝代码.
假设T是TItemDescendant,编译器允许编译和执行错误代码.如果LoadAll调用AList.Add(TItem.Create),则AList将最终保留不是TItemDescendant的内容,即使它是TObjectList< TItemDescendant>.它包含一个与其泛型类型参数所表示的类型不同的对象.
仅仅因为S是T的子类型并不意味着X< S>是X T的亚型.