Python中的抽象类 + 混入 + 多重继承

36 投票
2 回答
20120 浏览
提问于 2025-04-15 11:24

我觉得代码可能比我用语言解释得更清楚,所以我直接上代码:

import abc

class foo(object):
    __metaclass__ = abc.ABCMeta
    @abc.abstractmethod
    def bar(self):
        pass


class bar_for_foo_mixin(object):
    def bar(self):
        print "This should satisfy the abstract method requirement"


class myfoo(foo, bar_for_foo_mixin):
    def __init__(self):
        print "myfoo __init__ called"
        self.bar()

obj = myfoo()

结果是:

TypeError: Can't instantiate abstract class myfoo with abstract methods bar

我想让这个混合类满足抽象类或接口类的要求。我缺少了什么呢?

2 个回答

1

我觉得(在类似的情况下测试过)反转基类是有效的:

class myfoo(bar_for_foo_mixin, foo):
    def __init__(self):
        print "myfoo __init__ called"
        self.bar()

这样在 mro() 中,它会先找到 bar() 的具体实现,而不是抽象的那个。不过我不确定这在后台到底是怎么运作的。

谢谢,Lars

附注:在 Python 2.7 中有效的代码(Python 3 有不同的方式来设置 metaclass)是:

class A(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def do(self):
        pass

class B(object):
    def do(self):
        print "do"

class C(B, A):
    pass

c = C()
32

难道继承的顺序不应该反过来吗?在这个方法解析顺序(MRO)中,foo 现在排在 bar_for_foo_mixin 之前,所以它才会抱怨。用 class myfoo(bar_for_foo_mixin, foo) 这样写应该就能正常工作了。

而且我不太确定你的类设计是不是正确的。因为你用一个混入类来实现 bar,可能不需要从 foo 继承,直接把它注册到 'foo' 类里会更好(也就是 foo.register(myfoo))。不过这只是我个人的感觉。

为了完整起见,这里有关于 ABC 的 文档链接

撰写回答