为什么我不能将TObjectList <S:T>传递给期望TObjectList <T>的函数?

rob*_*rtw 8 delphi generics tobjectlist

我的代码有问题,它使用泛型类型.为什么编译器不知道传递的list(Result)是一个TObjectList<TItem>(TItemTin的类型TItems)?

接口:

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;
Run Code Online (Sandbox Code Playgroud)

执行:

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;
Run Code Online (Sandbox Code Playgroud)

Rob*_*edy 3

在出现错误的函数中,Resultis a TObjectList<T>,其中T是 的某个子类TItem,但编译器不知道它具体是什么类。编译器必须对其进行编译,以便可以安全地运行任何T. 这可能与 的参数类型不兼容LoadAll,后者需要 a TObjectList<TItem>,因此编译器会拒绝该代码。

假设TTItemDescendant,编译器允许错误代码编译并执行。如果LoadAll调用AList.Add(TItem.Create),那么AList最终会持有不是 a 的东西TItemDescendant,即使它是 a TObjectList<TItemDescendant>。它持有的对象的类型不同于其泛型类型参数所表示的类型。

仅仅因为S是 的子类型T并不意味着它X<S>是 的子类型X<T>