これは分かりやすかった。引っ掛かったところは
- 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 件のコメント:
コメントを投稿