Classe astratta + mixin + eredità multipla in python
-
05-07-2019 - |
Domanda
Quindi, penso che il codice probabilmente spieghi cosa sto cercando di fare meglio di quanto posso in parole, quindi ecco qui:
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()
Il risultato:
TypeError: Can't instantiate abstract class myfoo with abstract methods bar
Sto cercando di ottenere la classe mixin per soddisfare i requisiti della classe abstract / interface. Cosa mi sto perdendo?
Soluzione
L'eredità non dovrebbe essere al contrario? Nel MRO foo
viene attualmente prima bar_for_foo_mixin
, e quindi si lamenta giustamente. Con class myfoo (bar_for_foo_mixin, foo)
dovrebbe funzionare.
E non sono sicuro che il tuo design di classe sia il modo giusto per farlo. Dato che usi un mixin per implementare bar
potrebbe essere meglio non derivare da foo e registrarlo semplicemente con la classe 'foo' (es. foo.register (myfoo)
) . Ma questo è solo il mio istinto.
Per completezza, ecco la documentazione per ABC .
Altri suggerimenti
Penso (testato in un caso simile) che invertire le basi funziona:
class myfoo(bar_for_foo_mixin, foo):
def __init__(self):
print "myfoo __init__ called"
self.bar()
quindi in mro () troverà una versione concreta di bar () prima di trovare quella astratta. Non ho idea se questo sia effettivamente ciò che accade in background.
Saluti, Lars
PS: il codice che funzionava in python 2.7 (python 3 ha un modo diverso di impostare le metaclasse) era:
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()