我知道如何做到但又忘记了......非常恼火,因为我正在开发一个包含XML文件列表的类,现在我只想使用for-in循环来遍历所有此列表中的文件。这是我现在的课程:
type
TXmlFileList = class( TInterfacedObject )
private
type
TItem = class( TInterfacedObject )
strict private
FCaption: string;
protected
constructor Create( const ACaption: string; const AXML: WideString );
public
destructor Destroy; override;
property Caption: string read FCaption;
end;
strict private
FXmlFiles: array of TXmlFileList.TItem;
strict protected
function GetXmlFile( index: Integer ): TXmlFileList.TItem;
public
constructor Create( );
destructor Destroy; override;
function Add( const ACaption: string; const AXML: WideString ): Integer; overload;
function Add( const AFilename: string ): Integer; overload;
function Count: Integer;
procedure Clear;
property XmlFile[ index: Integer ]: TXmlFileList.TItem read GetXmlFile; default;
end;
看起来好笑吗? :-)我知道,但我想隐藏TXmlFile类的定义到外面的世界。基本上,TXmlFileList类允许我简单地引用XmlFileList [I]来获取位置I的文件。很好地工作。
但是现在我想循环遍历TXmlFileList.TItem元素,所以我必须公开TXmlFileList.TItem类。但这还不够。它在TXmlFileList类中也需要一个枚举器!
如何创建该枚举器?
您可能想知道为什么我使用这种复杂的结构。好吧,它可能很复杂但是它会被其他一些开发人员使用,我不想提供比他们需要的更多的方法。这样,我只给他们方法“Add”,“Clear”和“Count”循环遍历列表,以及TItem本身定义的任何属性。他们不需要更多,但我可能会在稍后添加更多功能......
答案 0 :(得分:2)
type
TItemEnumerator = class( TObject )
strict private
FOwner: TXmlFileList;
FIndex: Integer;
protected
constructor Create(AOwner: TXmlFileList);
public
function GetCurrent: TItem;
function MoveNext: Boolean;
property Current: TItem read GetCurrent;
end;
实现很简单,只是TXmlFileList的另一种方法:
function GetEnumerator: TItemEnumerator;
最后,将该类暴露给外部世界,我将其添加到TXmlFileList:
type TXmlFile = TXmlFileList.TItem;
是的,那脏! :-)
导致此代码:
type
TXmlFileList = class( TInterfacedObject )
private
type
TItem = class( TInterfacedObject )
strict private
FCaption: string;
protected
constructor Create( const ACaption: string; const AXML: WideString );
public
destructor Destroy; override;
property Caption: string read FCaption;
end;
type
TItemEnumerator = class( TObject )
strict private
FOwner: TXmlFileList;
FIndex: Integer;
protected
constructor Create(AOwner: TXmlFileList);
public
function GetCurrent: TItem;
function MoveNext: Boolean;
property Current: TItem read GetCurrent;
end;
strict private
FXmlFiles: array of TXmlFileList.TItem;
strict protected
function GetXmlFile( index: Integer ): TXmlFileList.TItem;
public
type TXmlFile = TXmlFileList.TItem;
constructor Create( );
destructor Destroy; override;
function Add( const ACaption: string; const AXML: WideString ): Integer; overload;
function Add( const AFilename: string ): Integer; overload;
function Count: Integer;
function GetEnumerator: TItemEnumerator;
procedure Clear;
property XmlFile[ index: Integer ]: TXmlFileList.TItem read GetXmlFile; default;
end;
是的,当你看到它时,你可以开始摸不着头脑,但这是一个很好的解决方案,可以隐藏无经验的开发人员的许多功能!现在他们只看到他们需要看到的东西。 (希望他们永远不会看到这个源代码!)我只是期望我需要写更多的代码而不是......
为什么要使用不同的名称公开TItem类型?实际上,这些类再次包装在一个更大的类TXmlManager中,该类还处理样式表,转换,验证和一堆其他东西。 TXmlFile实际上是在TXmlManager级别公开的,而不是TXmlFileList类。 TXmlManager包含一些其他类似的列表,我只是重新使用名称TItem。但是,没有冲突,因为需要添加父级来引用正确的类类型。
虽然类标题可能看起来很复杂,有近200行代码,但单元的其余部分相当纤薄,有近700行代码和大量注释。类结构实际上帮助我从使用它的人的角度简单地看待它。使用它的人不需要寻找使用的类型和方法。他们的选择非常有限......