29

だから、コードはおそらく私が言葉でできるよりもうまくやろうとしていることを説明していると思うので、ここに行きます:

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

抽象/インターフェースクラスの要件を満たすためにミックスインクラスを取得しようとしています。私は何が欠けていますか?

4

2 に答える 2

26

継承は逆にすべきではありませんか?MROでは、foo現在、の前に来て、当然のbar_for_foo_mixinことながら文句を言います。それでclass myfoo(bar_for_foo_mixin, foo)動作するはずです。

そして、あなたのクラスのデザインがそれを行う正しい方法であるかどうかはわかりません。実装にはミックスインを使用するのでbar、fooから派生せずに、「foo」クラス(つまりfoo.register(myfoo))に登録する方がよい場合があります。しかし、これは私の直感です。

完全を期すために、ここにABCのドキュメントがあります。

于 2009-05-05T17:49:37.620 に答える
1

私は(同様のケースでテストされた)ベースクラスを逆にすることが機能すると思います:

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

したがって、mro()では、抽象バージョンを見つける前に、bar()の具体的なバージョンを見つけます。しかし、これが実際にバックグラウンドで発生することであるかどうかはわかりません。

乾杯、ラース

PS:Python 2.7で機能したコード(Python 3ではメタクラスを設定する方法が異なります)は次のとおりです。

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()
于 2013-09-06T10:25:40.343 に答える