Абстрактный класс + миксин + множественное наследование в Python

StackOverflow https://stackoverflow.com/questions/825945

Вопрос

Итак, я думаю, что код, вероятно, объясняет то, что я пытаюсь сделать лучше, чем я могу на словах, поэтому здесь идет

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

Я пытаюсь заставить класс mixin удовлетворять требованиям абстрактного / интерфейсного класса. Чего мне не хватает?

Это было полезно?

Решение

Разве наследование не должно быть наоборот? В MRO foo в настоящее время предшествует bar_for_foo_mixin , а затем по праву жалуется. С классом myfoo (bar_for_foo_mixin, foo) это должно работать.

И я не уверен, что дизайн вашего класса - верный способ сделать это. Поскольку вы используете миксин для реализации bar , может быть лучше не наследовать от foo, а просто зарегистрировать его в классе 'foo' (т.е. foo.register (myfoo) ) , Но это только мое внутреннее чувство.

Для полноты вот документация по азбуке .

Другие советы

я думаю (проверено в аналогичном случае), что реверсирование базовых классов работает:

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()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top