根据参数类型在A类上调用方法

时间:2009-12-18 15:17:10

标签: python oop

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"
        ...

我不喜欢if/elifmanager()阻止查看并重构的方式:

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类中调用一个方法,根据其中一个参数的类,它会触发A中不同方法的调用?

PS。对于人为的例子感到抱歉,但发布实际代码会让问题更加复杂。我试图将问题提炼到其本质......

4 个答案:

答案 0 :(得分: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 )

答案 1 :(得分:1)

您试图模仿极客称之为“multiple dispatch”或“多方法”的语言。链接到维基百科的文章有很好的讨论,包括Python示例。

答案 2 :(得分: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)

答案 3 :(得分:0)

我通常在处理消息时这样做,所以我没有大量的ifs ......但它仍然使用类名。

一种穷人的多态性 - 但正如S.Lott所说,Python支持真正的多态,所以为什么不使用它:p

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