8

ジェネリック型を使用するコードに問題があります。Result渡されたリスト ( ) がTObjectList<TItem>( in のTItem型である) であることをコンパイラが認識しないのはなぜですか?TTItems

インターフェース:

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

2 に答える 2

4

ローダーの汎用バージョンも使用する必要があります。

type
   TItem = class
end;

type
  IItemsLoader<T: TItem> = interface
    procedure LoadAll(AList : TObjectList<T>);
end;

type
  TItemsLoader<T: TItem> = class(TInterfacedObject, IItemsLoader<T>)
public
  procedure LoadAll(AList : TObjectList<T>);
end;

type
  IItems<T : TItem> = interface
  function LoadAll : TObjectList<T>;
end;

type
  TItems<T : TItem> = class(TInterfacedObject, IItems<T>)
  private
    FItemsLoader : TItemsLoader<T>;
  public
    constructor Create;
    destructor Destroy; override;
    function LoadAll : TObjectList<T>;
end;


implementation

{$R *.dfm}

procedure TItemsLoader<T>.LoadAll(AList: TObjectList<T>);
begin
  /// some stuff with AList
end;

{ TItems<T> }

constructor TItems<T>.Create;
begin
  FItemsLoader := TItemsLoader<T>.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;
于 2012-04-27T21:46:42.980 に答える
3

エラーのある関数では、Resultは ですTObjectList<T>。ここで、Tは のサブクラスですTItemが、コンパイラはそれがどの特定のクラスであるかを認識していません。コンパイラは、 の任意の値に対して安全に実行できるようにコンパイルする必要がありTます。LoadAllこれは、 を必要とするの引数の型と互換性がない可能性があるTObjectList<TItem>ため、コンパイラはコードを拒否します。

が であると仮定するTTItemDescendant、コンパイラは問題のあるコードのコンパイルと実行を許可します。LoadAllを呼び出すと、AList.Add(TItem.Create).であっても、 でAListはないものを保持することになります。ジェネリック型パラメーターが保持していると言っているものとは異なる型のオブジェクトを保持しています。TItemDescendantTObjectList<TItemDescendant>

Sが のサブタイプだからといって、が のサブタイプでTあるとは限りません。X<S>X<T>

于 2012-04-27T17:51:15.420 に答える