電気通信大学で情報系(通信系?)らしきことを学んだが、不幸な事にオブジェクト指向プログラミングに触れる機会が無かった。プログラムと言えば講義の課題と数学の研究の実験のみでオブジェクト指向プログラミングを知らなくても生きていける環境にあった。そして現在、仕事でプログラミングを行っている。OJT(お前が 自分で トレーニング)な会社であるためこのままでは常識を知らぬまま時が過ぎし恥を晒すことになる。恥をかくならば今しかない。会社でちょっとJavaを扱ったのをいい機会に今更ながらデザインパターンを学ぼうかと思い立った。デザインパターンの原典といてば言わずもがなGoFである。
- 作者: エリックガンマ,ラルフジョンソン,リチャードヘルム,ジョンブリシディース,Erich Gamma,Ralph Johnson,Richard Helm,John Vlissides,本位田真一,吉田和樹
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 1999/10
- メディア: 単行本
- 購入: 21人 クリック: 711回
- この商品を含むブログ (206件) を見る
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/06/19
- メディア: 大型本
- 購入: 51人 クリック: 762回
- この商品を含むブログ (399件) を見る
GoFによると、「リストのような集約オブジェクトは、その内部構造を明らかにすることなく、要素にアクセスする方法をユーザに対して提供するべきである」(P275)とある。集約オブジェクトからアクセスや走査のための役割を取り出して扱うとよいとのことである…うーん、本当にわかっているのだろうか。
以下はPythonで書き直したIteratorパターンの例である。問題は、Pythonのリスト、タプル、集合には既にイテレータが定義してあるので以下のように行う必要があるのかいう疑問が湧いてくるのである…。なお、PythonにはJavaのようなインターフェースは存在しないが、抽象基底クラスを用いれば一応実現できる。
import collections.abc class Book(object): def __init__(self, name): self.name = name def getname(self): return self.name class BookShelf(collections.abc.Iterable): def __init__(self): self.__books = [] def getbookat(self, index): return self.__books[index] def appendbook(self, book): self.__books.append(book) def __len__(self): return len(self.__books) def __iter__(self): return BookShelfIterator(self) class BookShelfIterator(collections.abc.Iterator): __index = 0 def __init__(self, bookshelf): self.__bookshelf = bookshelf def __next__(self): try: ret = self.__bookshelf.getbookat(self.__index) self.__index += 1 return ret except IndexError: raise StopIteration if __name__ == '__main__': bookshelf = BookShelf() bookshelf.appendbook(Book("ドラえもん")) bookshelf.appendbook(Book("パーマン")) bookshelf.appendbook(Book("キテレツ大百科")) bookshelf.appendbook(Book("オバケのQ太郎")) for book in bookshelf: print(book.getname()) for book in bookshelf: print(book.getname())
なんだか、もやもやする。
collections.abc.Iterableをが__iter__()を提供している、というのが「アクセスや走査のための役割を取り出して扱う」を意味するのだろうか。ユーザにcollections.abc.Iteratorを継承したイテレータを書かせることがIteratorパターンの旨み、なのか?