(delphi11最新学习资料) Object Pascal 学习笔记---第10章第5节(实现类的枚举支持)

10.5 实现类的枚举支持

​ 在第3章中,我们已经看到了如何使用for-in循环作为经典for循环的替代方法。在那一节中,我描述了如何将for-in循环用于数组,字符串,集合和一些其他系统数据类型。只要类定义了枚举支持,就可以将这种循环应用于该类。尽管最明显的示例是包含元素列表的类,但从技术角度来看,此功能是相当开放的。

​ 要在Object Pascal 中支持枚举类中的元素,必须添加一个名为 GetEnumerator 的方法,该方法返回一个类(实际的枚举类),并使用 MoveNext 方法和 Current 属性定义这个枚举类——前者用于在元素之间导航,后者用于返回实际的元素。完成这个步骤以后(我将在第二个实际示例中向您展示如何完成),编译器就可以解析for-in循环,其中目标是我们类,单独元素必须是枚举器的Current属性的相同类型。一旦这样做了(稍后我将在一个实际例子中向你展示如何做),编译器就可以解析一个for-in循环,其中的目标是我们的类,而各个元素必须与枚举器的Current属性的类型相同。

​ 虽然说并不是严格必要,但把枚举器支持类作为嵌套类型来实现似乎是个好主意(这是第 7 章中涉及的一种语言特性),因为单独使用用于枚举的特定类型毫无意义。

​ 下面这个类是 NumbersEnumerator 示例的一部分,它存储了一系列数字(一种抽象集合),并允许对它们进行迭代。这是通过定义一个枚举器实现的,枚举器被声明为嵌套类型,并由 GetEnumerator 函数返回:

type
  TNumbersRange = class
  public
    type
      TNumbersRangeEnum = class
      private
        NPos: Integer;
        FRange: TNumbersRange;
      public
        constructor Create(ARange: TNumbersRange);
        function MoveNext: Boolean;
        function GetCurrent: Integer;
        property Current: Integer read GetCurrent;
      end;
  private
    FNStart: Integer;
    FNEnd: Integer;
  public
    function GetEnumerator: TNumbersRangeEnum;
    procedure Set_NEnd(const Value: Integer);    
    procedure Set_NStart(const Value: Integer);
    property NStart: Integer read FNStart write Set_NStart;
    property NEnd: Integer read FNEnd write Set_NEnd;
  end;

GetEnumerator方法创建了一个嵌套类的对象,用于存储对数据进行迭代的状态信息。

​ 请注意枚举器构造函数是如何保持对实际枚举对象(使用 Self 作为参数传递的对象)的引用,并将初始位置设置为起始位置的:

function TNumbersRange.GetEnumerator: TNumbersRangeEnum;
begin
  Result := TNumbersRangeEnum.Create(Self);
end;

constructor TNumbersRange.TNumbersRangeEnum.Create(ARange: TNumbersRange);
begin
  inherited Create;
  FRange := ARange;
  NPos := FRange.NStart - 1;   //sets the initial positon to the very beginning
end;

注意 为什么构造函数将初始值设置为第一个值减 1,而不是预想中的第一个值呢?实际上,编译器生成的 for-in 循环的代码相当于:首先创建了一个枚举器(enumerator),然后在 MoveNext 返回 True 的情况下执行代码,一直循环直到 MoveNext 返回 False,在循环中使用 Current 方法获取当前元素的值。测试是在获取第一个值之前进行的,因为列表可能没有值。这意味着 MoveNext 会在第一个元素被使用之前被调用。我没有使用更复杂的逻辑来实现这一点,而是简单地将初始值设置为第一个值之前的一个值,这样在第一次调用 MoveNext 时,枚举器就会被定位在第一个值上。

​ 最后,枚举器方法可以让你访问数据,并提供一种方法移动到列表中的下一个值(或范围内的下一个元素):

function TNumbersRange.TNumbersRangeEnum.GetCurrent: Integer;
begin
  Result := NPos;
end;

function TNumbersRange.TNumbersRangeEnum.MoveNext: Boolean;
begin
  Inc(NPos);
  Result := NPos <= FRange.NEnd;
end;

​ 正如你在上面的代码中所看到的,MoveNext 方法有两个不同的目的:移动到列表的下一个元素,以及检查枚举器是否已经到达终点(在这种情况下,该方法返回 False)。

​ 完成所有这些工作后,现在就可以使用for-in循环遍历 range 对象的值了:

​ 输出结果就是介于 10 和 23 之间(包括 10 和 23)的枚举值列表:

10
11
12
13
14
15
16
17
18
19
20
21
22
23

注意: 在 RTL(Run-Time Library) 和 VCL(Visual Component Library) 库中,有许多情况下都定义了枚举器,例如,每个 TComponent 都可以枚举它所拥有的组件。目前缺少的是子控件的枚举。在第 12 章的“使用类助手添加枚举”部分,我们将看到如何创建这样一个枚举。之所以这个示例不在这里,是因为我们首先需要讨论类助手(class helpers)。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi XE是一种基于Object Pascal编程语言的集成开发环境(IDE),用于开发Windows平台上的应用程序。类是Delphi编程中的重要概念,它是面向对象编程的基础。 在Delphi XE中,类用于封装数据和方法,以创建可重用的代码块。一个类可以有属性和方法,属性用于访问和修改对象的数据,而方法用于执行特定的操作。通过使用类和对象,可以实现代码的模块化和组织,以提高代码的可维护性和重用性。 在学习Delphi XE的类编程时,需要掌握以下几个关键概念: 1. 类的定义:使用class关键字来定义一个类,可以在类中声明属性和方法。 2. 对象的创建:通过使用类来创建对象,可以通过实例化类的方式来创建对象,并使用对象来调用类中的方法和访问属性。 3. 继承与多态:Delphi XE支持继承和多态的特性,允许一个类从另一个类继承属性和方法,并可以通过多态的方式重写父类的方法。 4. 类的访问控制:可以使用访问修饰符(如private、protected、public、published)来控制类中属性和方法的访问权限。 通过深入学习Delphi XE的类编程,可以掌握面向对象编程的核心思想和技巧,能够更好地利用Delphi XE的特性和功能来开发高质量的应用程序。同时,熟练掌握类编程还能够提高代码的可读性和可维护性,使代码更易于理解和修改。 综上所述,Delphi XE的类学习学习Delphi编程的重要内容。通过深入了解类的概念、属性、方法、继承、多态和访问控制等知识点,可以编写出更高效、可扩展和易维护的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值