B/C - Iterator
- Category: behavioral
- Type: class
- Motivation: provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation
do {
let list = List()
list.add(Item(title: "foo"))
list.add(Item(title: "bar"))
list.add(Item(title: "baz"))
var iterator = list.makeIterator()
while let item = iterator.next() {
print(item)
}
}
protocol Iterator
{
associatedtype Element
func next() -> Element?
}
struct ListIterator: Iterator
{
var index: Int = -1
var count: Int = 0
let list: List
init(_ list: List)
{
self.list = list
self.count = list.count
}
typealias Element = Item
mutating func next() -> Element?
{
index += 1
if index >= count {
return nil
}
return self.list[index]
}
}
struct Item
{
let title: String
}
protocol Container
{
associatedtype Element
var count: Int { get }
subscript(_ index: Int) -> Element { get }
func add(_ element: Element)
func remove(at index: Int)
associatedtype Iterator
func makeIterator() -> Iterator
}
class List: Container {
var elements: [Item] = []
typealias Element = Item
var count: Int { elements.count }
subscript(_ index: Int) -> Element
{
elements[index]
}
func add(_ element: Element)
{
elements.append(element)
}
func remove(at index: Int)
{
elements.remove(at: index)
}
func makeIterator() -> ListIterator
{
ListIterator(self)
}
}