これは分かりやすかった。引っ掛かったところは
- IteratorはAggregate(集合体)があって初めて意味を持つので、その集合体にIteratorを作成するメソッドを持たせる
- next()は現在のインデックスの値を返す
- hasNext()はnext()が呼べるかどうかという真偽値を返す
応用1 ― pythonで実装
練習問題をやってもいいのだけど、ここのところpythonを使う機会が多いのでpythonでIteratorパターンを書いてみようと思います。
教本と同じBookshelfを実装してみるとこんな感じになりました。
#!/usr/bin/env python class __Aggregator: def __init__(self): raise Exception('abstract class') def iterator(self): raise Exception('iterator() must be implemented') class __Iterator: def __init__(self): raise Exception('abstract class') def next(self): raise Exception('next() must be implemented') def hasNext(self): raise Exception('hasNext() must be implemented') class Bookshelf(__Aggregator): def __init__(self): self.__books = [] def getBookAt(self, index): return self.__books[index] def appendBook(self, book): self.__books.append(book) def getLength(self): return len(self.__books) def iterator(self): return BookshelfIterator(self) class Book: def __init__(self, name): self.__name = name def getName(self): return self.__name class BookshelfIterator(__Iterator): def __init__(self, bookshelf): self.__bookshelf = bookshelf self.__index = 0 def next(self): book = self.__bookshelf.getBookAt(self.__index) self.__index += 1 return book def hasNext(self): return self.__index < self.__bookshelf.getLength() def main(): bookshelf = Bookshelf() bookshelf.appendBook(Book("Around the World in 80 Days")) bookshelf.appendBook(Book("Bible")) bookshelf.appendBook(Book("Cinderella")) bookshelf.appendBook(Book("Daddy-Long-Legs")) it = bookshelf.iterator() while it.hasNext(): print it.next().getName() if __name__=='__main__': main()
pythonにはJavaでいうインターフェイスや抽象クラスの概念はないので、アンダースコアを2つつけて明示化してあります。それ以外は何の変哲もなし。実行結果も同じ。
応用2 ― もっと簡単なpythonでの実装
調べてみると、pythonにはイテレータを実装する仕組みが既にあった。
http://www.python.jp/doc/2.5/tut/node11.html#SECTION0011800000000000000000
(というかあったけどあえて自分で書いてた。勉強ですからね)
前のとの違いは
応用2 ― もっと簡単なpythonでの実装
調べてみると、pythonにはイテレータを実装する仕組みが既にあった。
http://www.python.jp/doc/2.5/tut/node11.html#SECTION0011800000000000000000
(というかあったけどあえて自分で書いてた。勉強ですからね)
前のとの違いは
- hasNext()は無くて、next()を呼んだときに値がなければ例外StopIterationを投げる
- 利用側がnext()を直接呼ばない。代わりにfor loopを使う
#!/usr/bin/env python class __Aggregator: def __init__(self): raise Exception('abstract class') def iterator(self): raise Exception('iterator() must be implemented') class Bookshelf(__Aggregator): def __init__(self): self.__books = [] def getBookAt(self, index): return self.__books[index] def appendBook(self, book): self.__books.append(book) def getLength(self): return len(self.__books) def iterator(self): return BookshelfIterator(self) class Book: def __init__(self, name): self.__name = name def getName(self): return self.__name class BookshelfIterator(): def __init__(self, bookshelf): self.__bookshelf = bookshelf self.__index = 0 # 以下の2関数を実装することがIteratorを実装することと等価 def __iter__(self): return self def next(self): if self.__index >= self.__bookshelf.getLength(): raise StopIteration book = self.__bookshelf.getBookAt(self.__index) self.__index += 1 return book def main(): bookshelf = Bookshelf() bookshelf.appendBook(Book("Around the World in 80 Days")) bookshelf.appendBook(Book("Bible")) bookshelf.appendBook(Book("Cinderella")) bookshelf.appendBook(Book("Daddy-Long-Legs")) it = bookshelf.iterator() for b in it: print b.getName() if __name__=='__main__': main()
ごちそうさまでした。
0 件のコメント:
コメントを投稿