好吧,这可能会令人困惑。我想要做的是使用枚举器只返回基于类类型的通用列表中的某些项目。
给定以下层次结构:
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
器上使用Primoz Gabrijelcic 的修改版本进行扩展,如下所示:
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
关于Incompatible types: TCircle and TShape
. 如果我注释掉TCircle
循环,那么我会收到类似的错误TSquare
。如果我TSquare
也将循环注释掉,代码就会编译并工作。好吧,它的工作原理是枚举每个对象,因为它们都来自TShape
. 奇怪的是,编译器指示的行号是文件末尾之外的 2 行。在我的演示项目中,它表示第 177 行,但只有 175 行。
有什么办法可以使这项工作?我希望能够直接分配给 Circle 而无需经过任何类型转换或检查我的for
循环本身。