SwiftでIteratorパターン

[こちら](https://www.techscore.com/tech/DesignPattern/Iterator/Iterator1)の記事で記載されている演習内容をSwiftで写経させていただきました。

ざっくりまとめ
1. 集約体を操作するIteratorプロトコルを作成(hasNext(), next())
1. Iteratorに準拠したConcreateIteratorクラスを作成(Aggregateプロトコルに準御したクラスをプロパティで持つ)
1. Iteratorプロトコルの実体を返却するAggregateプロトコルを作成(iterator())
1. Aggregateプロトコルに準拠したConcreateAggregateクラスでIteratorクラスを生成する(ConcreateIteratorクラスを返却する)

```swift

/*
 「Teacher」抽象クラスを継承する MyTeacher クラスと、「StudentList」クラスを拡張した MyStudentList クラスを設計しクラス図を作成しなさい。また、これらのクラスを実装し、 下記のMain クラスを実行しなさい。この２つのクラス以外のクラスやインタフェースを自由に追加しても問題ありません。 MyTeacher クラスの callStudents メソッドでは、あなたのクラスの生徒を順番に標準出力に出力するようにしなさい。
 あなたのクラスの生徒は、

 赤井亮太　男
 赤羽里美　女
 岡田美央　女
 西森俊介　男
 中ノ森玲菜　女
 の5人とします。
 */

// Sample
class Student {
    private let name: String
    private let sex: Int
    
    init(name: String, sex: Int) {
        self.name = name
        self.sex = sex
    }
    
    func getName() -> String {
        name
    }
    
    func getSex() -> Int {
        sex
    }
}

class StudentList {
    var student: [Student]
    private var last = 0
    
    init(studentCount: Int) {
        self.student = Array(repeating: Student(name: "", sex: 0), count: studentCount)
    }
    
    func add(student: Student) {
        self.student[last] = student
        last += 1
    }
    
    func getStudentAt(index: Int) -> Student {
        student[index]
    }
    
    func getLastNumber() -> Int {
        last
    }
}

protocol Teacher {
    var studentList: StudentList { get }
    func createStudentList()
    func callStudents()
}

//class MyTeacher: Teacher {
//    var studentList: StudentList
//    
//    init() {
//        self.studentList = MyStudentList(studentCount: 5)
//    }
//    
//    func createStudentList() {
//        studentList.add(student: Student(name: "赤井亮太", sex: 1))
//        studentList.add(student: Student(name: "赤羽里美", sex: 2))
//        studentList.add(student: Student(name: "岡田美央", sex: 2))
//        studentList.add(student: Student(name: "西森俊介", sex: 1))
//        studentList.add(student: Student(name: "中ノ森玲菜", sex: 2))
//    }
//    
//    func callStudents() {
//        for i in 0 ..< studentList.getLastNumber() {
//            print(studentList.getStudentAt(index: i).getName())
//        }
//    }
//}

// 集約体を操作するために必要なメソッドを定義(Interactor)
protocol Iterator {
    /// この集約体に次の要素が存在するかどうか
    func hasNext() -> Bool
    /// 次の要素を返却する
    func next() -> AnyObject
}

// Iteratorプロトコルの実装クラスを返却する(Aggregate)
protocol Aggregate {
    func iterator() -> Iterator 
}

/*
	MyStudentList クラスと、MyStudentListIterator クラスを実装しなさい。 ただし、MyStudentList クラスは、以前の古い名簿 StudentList を拡張したものにすること。
*/

// Aggregateプロトコルを実装する必要があり、Iteratorプロトコルに準拠したクラスを作成する必要がある(ConcreateAggregate)
class MyStudentList: StudentList, Aggregate {
    func iterator() -> Iterator {
        MyStudentListIterator(list: self)
    }
}

// ConcreateIteratorクラス
class MyStudentListIterator: Iterator {
    private let myStudentList: MyStudentList
    private var index: Int
    
    init(list: MyStudentList) {
        self.myStudentList = list
        index = 0
    }
    
    func hasNext() -> Bool {
        myStudentList.getLastNumber() > index
    }
    
    func next() -> AnyObject {
        let student = myStudentList.getStudentAt(index: index)
        index += 1
        return student
    }
}

class MyTeacher: Teacher {
    var studentList: StudentList
    
    init() {
        self.studentList = MyStudentList(studentCount: 5)
    }
    
    func createStudentList() {
        studentList.add(student: Student(name: "赤井亮太", sex: 1))
        studentList.add(student: Student(name: "赤羽里美", sex: 2))
        studentList.add(student: Student(name: "岡田美央", sex: 2))
        studentList.add(student: Student(name: "西森俊介", sex: 1))
        studentList.add(student: Student(name: "中ノ森玲菜", sex: 2))
    }
    
    func callStudents() {
        let itr: Iterator = (studentList as! MyStudentList).iterator()
        while itr.hasNext() {
            print((itr.next() as! Student).getName())
        }
    }
}

let you: Teacher = MyTeacher()
you.createStudentList()
you.callStudents()
/*
    java.util.Vector クラスを利用した新しい名簿に変更後に必要となる、NewVeteranStudentList クラスと NewVeteranStudentListIterator クラスを実装し、クラス図を作成しなさい。
    また、これに伴い VeteranTeacher クラスを変更しなさい。
     古い名簿を利用していた時の VeteranTeacher クラスは下記のように実装されています。
*/
class NewVeteranStudentList: StudentList, Aggregate {
    func iterator() -> Iterator {
        NewVeteranStudentListIterator(list: self)
    }
}

class NewVeteranStudentListIterator: Iterator {
    let newVeteranStudentList: NewVeteranStudentList
    private var index = 0
    
    init(list: NewVeteranStudentList) {
        self.newVeteranStudentList = list
    }
    
    func hasNext() -> Bool {
        newVeteranStudentList.getLastNumber() > index
    }

    func next() -> AnyObject {
        let student = newVeteranStudentList.getStudentAt(index: index)
        index += 1
        return student
    }
}

class VeteranTeacher: Teacher {
    var studentList: StudentList
    
    init() {
        self.studentList = NewVeteranStudentList(studentCount: 3)
    }
    
    func createStudentList() {
        studentList.add(student: Student(name: "中川雄介", sex: 1))
        studentList.add(student: Student(name: "板東恵美", sex: 2))
        studentList.add(student: Student(name: "水島太郎", sex: 1))
    }

    func callStudents() {
        let iterator = (studentList as! NewVeteranStudentList).iterator()
        while iterator.hasNext() {
            print((iterator.next() as! Student).getName())
        }
    }
}

let veteranTeacher = VeteranTeacher()
veteranTeacher.createStudentList()
veteranTeacher.callStudents()
```

# 参考文献
- [TECHSCORE(テックスコア)](https://www.techscore.com/)