2009-12-18 64 views
4
class Class1(object): 
    ... 

class Class2(object): 
    ... 

class Class3(object): 
    ... 

class A(object): 
    def _methA(parm1, parm2) 
     ... 

    def _methB(parm1, parm2) 
     ... 

    def _methC(parm1, parm2) 
     ... 

    def manager(parm1, method, params) 
     ... 
     if parm1.__class__.__name__==Class1.__name__: 
      response = _methA(parm1, params) 
     elif parm1.__class__.__name__==Class2.__name__: 
      response = _methB(parm1, params) 
     elif io_source.__class__.__name__==Class3.__name__: 
      response = _methC(parm1, params) 
     else: 
      raise Exception, "Unsupported parm1" 
     ... 

我不喜歡的方式,在manager()if/elif塊看着它重構爲這樣:上調用A類的方法取決於類型參數的

def manager(parm1, method, params) 
    ... 
    try: 
     response = { 
       Class1.__name__: lambda parm1, parms: _methA(parm1, parms), 
       Class2.__name__: lambda parm1, parms: _methB(parm1, parms), 
       Class3.__name__: lambda parm1, parms: _methC(parm1, parms) 
       }[parm1.__class__.__name__](parm1, parms) 
    except KeyError: 
     raise Exception, "Unsupported parm1" 

但事實證明代碼仍然在看類名困擾我 - 我真的不知道如何解釋爲什麼... 它應該打擾我嗎?

有沒有更好的方式來編寫代碼來調用A類的方法是,根據類的參數之一,觸發在不同的方法的調用?

PS。對不起這個人爲的例子,但發佈實際的代碼會讓問題變得更加複雜。我想這個問題要提煉其精髓...

+0

+1:這是最小的一段代碼的一個很好的例子顯示問題。 – 2009-12-18 15:41:09

回答

5

這是實現多態的許多錯誤方法之一。你不應該看類名。查看班級名稱會讓你感到困擾,因爲這意味着你沒有正確授予責任。

將每個方法移到相應的類中。

class Class1(object): 
    def method(self, theA, params): 
     theA.methA(params) 

class Class2(object): 
    def method(self, theA, params): 
     theA.methB(params) 

class Class3(object): 
    def method(self, theA, params): 
     theA.methC(params) 

class A(object): 
    def methA(parm1, parm2) 
     ... 

    def methB(parm1, parm2) 
     ... 

    def methC(parm1, parm2) 
     ... 

    def manager(parm1, method, params) 
     ... 
     param1.method(self, params) 
+0

+1表達爲什麼我覺得在查看類名稱的代碼時感到不安。 :-)是的,這是我們正在討論的事情之一 - 爲什麼這些方法沒有封裝在Class1,Class2和Class3中。在實際的代碼中有它的原因(雖然它們可能不是很好的理由)。 – cethegeek 2009-12-18 15:34:39

+2

@celopes:「他們可能不是很好的理由」 - 幾乎是正確的。他們不是很好的理由。他們「似乎」使「Class1」,「Class2」和「Class3」知道「A」的特徵;但是這個判斷是錯誤的。 A的「隱藏」方法真的是* A的公共接口。 – 2009-12-18 15:40:18

0

我寧願

if isinstance(parm1, Class1): 
    _methA(parm1, params) 
elif isinstance(parm1, Class2): 
    _methB(parm1, params) 
elif isinstance(parm1, Class3): 
    _methC(parm1, params) 

但仍聞起來有設計缺陷的。 :)

也許你的三類ClassX倒是應該都有一個單一的方法meth(params),那麼你的經理可能只是打電話parm1.meth(params)

1

您正試圖模擬哪種語言極客稱爲「multiple dispatch」或「multimethods」。鏈接到維基百科的文章有很好的討論,包括Python示例。

0

我通常做這種處理消息的時候,所以我沒有噸IFS的...但它仍然使用了類名。一個窮人的多態性

類 - 但是,正如美國洛特說,Python支持真正的多態,爲什麼不使用它:對

class Handler(object): 
    # .. stuff 

    def dispatch(self, msg): 
     handlername = "on_%s" % type(msg) 
     return getattr(self, handlername, 'on_missing_handler')(msg) 

    def on_SomeClass(self, msg): 
     # msg is of SomeClass here .. 

    def on_SomeOtherClass(self, msg): 
     # msg is of SomeOtherClass here .. 

    def on_missing_handler(self, msg): 
     # there is no other handler for msg 
相關問題