OOP への道:if と別れる50の方法《05》ジャンケン問題, double-dispatch

記事一覧if 篇for 篇配列 篇

Python.use(better) # OOP への道 《Python3.1, Jython2.5.0, IronPython2.6.x》
ジャンケン問題, double-dispatch

《著》真樹育未・後藤いるか・小粒ちゃん《監修》小泉ひよ子とタマゴ倶楽部
第0版♪1988/10/12 ● 第1版♪1993/05/23 ● 第2版♪2003/05/25

■ 概要

if/switch 文は多くの問題を抱え、OOP を実践するときの「障害」になります。

伝統的なC言語風の for 文や悪名高い switch 文、配列の呪縛から解かれ、オブジェクト指向プログラミング〔OOP〕の醍醐味を堪能するための準備を行います。

ジャンケン問題とは

承前


》作業中です《

double-dispatch

《Note》Smalltalk との出会いで印象深いもののひとつが double-dispatch です。単純なメカニズムでありなが、その用途は広く、OOP の神髄を垣間見る思いがしたものです。

■ double-dispatch
class Player(object):
    def __init__(self, id):
        self.id = id
    def __repr__(self):
        return "%s(%s)"%(self.__class__.__name__, self.id)
    def next(self):
        self.hand = (PlayerG, PlayerC, PlayerP)[randint(0, 2)]()
        return self.hand
    
def judge(self, player):
    return self.hand.judge(player.hand) 
■ 抽象クラス

抽象クラスでは、具象クラスに共通するプロトコルを規定します。

class Hand(object):
    def __repr__(self):
        return "(%s)"%(self.__class__.__name__)
    def judge(self, player):
        return eval("player.judgeFrom%s(self)"%self.__class__.__name__)

メソッド judge の意味(意義)を、メッセージ送受信に沿って説明します。

送信者 player から、メッセージ judge を受信したときには、player の手は3つの選択肢のひとつに確定しています。しかし、それが具体的に何かを受信者 self は、知る必要はありません。その代わり、自分 self がどの手を選択したかは、メッセージを受信したときにはすでに確定しています。

たとえば、R(rock) を選択したなら、それは次のように、

    def judge(self, player):
        return player.judgeFromPlayerR(self)

送信者 player に対して、受信者 self から、メッセージ judgeFromPlayerR が返信されます。


■ 具象クラス

具象クラスでは、勝者になるプレーヤー self,player か、引分を意味する None をリターン値にします。

class PlayerR(Hand):
    def judgeFromPlayerR(self, player): return None
    def judgeFromPlayerP(self, player): return player
    def judgeFromPlayerS(self, player): return self

class PlayerP(Hand):
    def judgeFromPlayerR(self, player): return self
    def judgeFromPlayerP(self, player): return None
    def judgeFromPlayerS(self, player): return player

class PlayerS(Hand):
    def judgeFromPlayerR(self, player): return player
    def judgeFromPlayerP(self, player): return self
    def judgeFromPlayerS(self, player): return None

》作業中です《

何が問題か:N人ジャンケンへの道

すべての if 文は消滅しました。しかし、これは望ましい結果でしょか。伝統的な if 文による解法と比べて、記述したコードの量はむしろ増えています。費用対効果を考えると、このアプローチは得策でないとも言えます。確かに、2人で対戦する場合はそのとおりですが、これが、3人以上、そして一般にn人で対戦する場合になると、その状況は一変します。

Tips

》作業中です《

Last updated♪2009/07/12