【问题标题】:Enumerating a custom array so I can use for-in枚举自定义数组,以便我可以使用 for-in
【发布时间】:2010-11-04 10:10:34
【问题描述】:

我知道该怎么做,但又忘记了... 很烦人,因为我正在处理一个包含 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 本身上定义的任何属性。他们不需要更多,尽管我稍后可能会添加更多功能......

【问题讨论】:

    标签: delphi winapi delphi-2007 enumeration


    【解决方案1】:

    找到了!我需要创建一个名为 TItemEnumerator 的新类,我还将它包含在 TXmlFileList 类中,就在 TItem 之后:

        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 行代码和大量 cmets。类结构实际上帮助我从使用它的人的角度来看它。使用它的人,不需要寻找类型和方法来使用。他们的选择非常有限......

    【讨论】:

    • TXmlFileList.TItem 如果你以后暴露它,为什么要设为私有?
    • 好问题。 :-) 基本上,我只是遵循一种模式,公开课程意味着打破这种模式。此外,如果我愿意,我总是可以决定让枚举器返回任何其他类型。例如,只是字幕。但后来我不得不将 TXmlFile 声明为 public。
    • Primoz 有一系列关于枚举器的文章,您可能会觉得有帮助:thedelphigeek.com/search/label/enumerators
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 2015-03-02
    相关资源
    最近更新 更多