VFP 开发者经常自我安慰的话就是“嗯,先交付,有时间再进行迭代”。
从这句话里,基本可以理解“迭代”的含义:重复,以之前结果为起点的重复的动作。放置编程的语境中,迭代器可以认为是对一组特定算法的抽象。
在 C#/X# 中,迭代器是继承自特定接口的抽象类。对于复杂的数据结构(例如树形),可以自定义迭代器。
迭代器模式存在的意义在于将算法和数据结构解耦。例如,你可以使用数组来存储数据,也可以使用集合来存储数据。如果单独的对数组和集合分别进行进行操作,那么,它们的实现代码总是有些不同。但是,借助迭代器模式,你可以使用同样的代码实现相同的“操作”。
迭代器模式的关键组件是迭代器接口和数据集合接口。迭代器接口,也就是算法的抽象;数据集合是对需要操作的数据结构的封装。
在 VFP 中,可以认为已经通过 Collection 类提供了基础的迭代功能,但对于复杂场景仍需手动实现完整迭代器模式。
VFP版的迭代器接口大概可以这样定义:
*!* 迭代器
Define Class Iterator As Custom
Procedure Key() As Number
Endproc
Procedure Current() As Object
Endproc
Procedure MoveNext() As Logical
Endproc
Procedure Reset()
Endproc
Enddefine
具体的迭代器继承自 Iterator。需要自行实现算法。例如,如果是针对(VFP的)集合,那么,具体的迭代器大概可以这样写:
Define Class CollectionIterator As Iterator
Protected oCollection = .Null.
Protected nPosition = 0 && 当前遍历的位置
Protected lReverse = .F. && .T. 正向遍历; .F. 反向遍历
Procedure Init(toCollection As Collection)
With This
.oCollection = m.toCollection
.lReverse = Iif(m.toCollection.KeySort = 0, .T., .F.)
EndWith
Endproc
Procedure Key() As Number
Return This.nPosition
Endproc
Procedure Current() As Object
Return This.oCollection.Item(This.nPosition)
Endproc
Procedure MoveNext() As Logical
Local lnUpdatePosition As Number
m.lnUpdatePosition = This.nPosition + Iif(This.lReverse, 1, -1)
If InList(m.lnUpdatePosition, 0, This.oCollection.Count
Return .T.
EndIf
Return .F.
Endproc
Procedure Reset()
This.nPosition = 0
Endproc
Enddefine
所以,我们的代码大概就是下面这个样子:
Local loCollection As Collection, loCollectionIterator As CollectionIterator
m.loCollection = CreateObject("Collection")
m.loCollection.Add("One")
m.loCollection.Add("Two")
m.loCollectionIterator = CreateObject("CollectionIterator", m.loCollection)
Do While m.loCollection.MoveNext()
? m.loCollectionIterator.Current()
EndDo