Абстрактный класс + миксин + множественное наследование в Python
-
05-07-2019 - |
Вопрос
Итак, я думаю, что код, вероятно, объясняет то, что я пытаюсь сделать лучше, чем я могу на словах, поэтому здесь идет
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()