さて、これは混乱するかもしれません。私がやろうとしているのは、列挙子を使用して、クラスタイプに基づいたジェネリックリスト内の特定のアイテムのみを返すことです。
次の階層があるとします。
type
TShapeClass = class of TShape;
TShape = class(TObject)
private
FId: Integer;
public
function ToString: string; override;
property Id: Integer read FId write FId;
end;
TCircle = class(TShape)
private
FDiameter: Integer;
public
property Diameter: Integer read FDiameter write FDiameter;
end;
TSquare = class(TShape)
private
FSideLength: Integer;
public
property SideLength: Integer read FSideLength write FSideLength;
end;
TShapeList = class(TObjectList<TShape>)
end;
次のようなことができるように拡張するにはどうすればよいTShapeList
ですか。
procedure Foo;
var
ShapeList: TShapeList;
Shape: TShape;
Circle: TCircle;
Square: TSquare;
begin
// Create ShapeList and fill with TCircles and TSquares
for Circle in ShapeList<TCircle> do begin
// do something with each TCircle in ShapeList
end;
for Square in ShapeList<TSquare> do begin
// do something with each TSquare in ShapeList
end;
for Shape in ShapeList<TShape> do begin
// do something with every object in TShapeList
end;
end;
次のように、ファクトリレコードを使用して、パラメータ化された列挙TShapeList
子でPrimozGabrijelcicのビットの適合バージョンを使用して拡張を試みました。
type
TShapeList = class(TObjectList<TShape>)
public
type
TShapeFilterEnumerator<T: TShape> = record
private
FShapeList: TShapeList;
FClass: TShapeClass;
FIndex: Integer;
function GetCurrent: T;
public
constructor Create(ShapeList: TShapeList);
function MoveNext: Boolean;
property Current: T read GetCurrent;
end;
TShapeFilterFactory<T: TShape> = record
private
FShapeList: TShapeList;
public
constructor Create(ShapeList: TShapeList);
function GetEnumerator: TShapeFilterEnumerator<T>;
end;
function FilteredEnumerator<T: TShape>: TShapeFilterFactory<T>;
end;
次に、次のように変更Foo
しました。
procedure Foo;
var
ShapeList: TShapeList;
Shape: TShape;
Circle: TCircle;
Square: TSquare;
begin
// Create ShapeList and fill with TCircles and TSquares
for Circle in ShapeList.FilteredEnumerator<TCircle> do begin
// do something with each TCircle in ShapeList
end;
for Square in ShapeList.FilteredEnumerator<TSquare> do begin
// do something with each TSquare in ShapeList
end;
for Shape in ShapeList.FilteredEnumerator<TShape> do begin
// do something with every object in TShapeList
end;
end;
Foo
ただし、についてコンパイルしようとすると、Delphi2010がエラーをスローしますIncompatible types: TCircle and TShape
。ループをコメントアウトすると、TCircle
について同様のエラーが発生しTSquare
ます。ループについてもコメントするTSquare
と、コードがコンパイルされて機能します。それは、すべてのオブジェクトがから派生しているため、すべてのオブジェクトを列挙するという意味で機能しますTShape
。奇妙なことに、コンパイラが示す行番号は、ファイルの終わりを2行超えています。私のデモプロジェクトでは、177行目が示されていましたが、175行しかありません。
これを機能させる方法はありますか?for
タイプキャストを実行したり、ループ自体をチェックインしたりせずに、Circleに直接割り当てることができるようにしたいと思います。