Classe abstraite + mixin + héritage multiple en python
-
05-07-2019 - |
Question
Donc, je pense que le code explique probablement ce que j'essaie de faire mieux que je ne peux le faire avec des mots, alors voici:
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()
Le résultat:
TypeError: Can't instantiate abstract class myfoo with abstract methods bar
J'essaie de faire en sorte que la classe mixin satisfasse aux exigences de la classe abstract / interface. Qu'est-ce qui me manque?
La solution
L'héritage ne devrait-il pas être l'inverse? Dans le MRO, toto
vient avant bar_for_foo_mixin
, puis se plaint à juste titre. Avec class myfoo (bar_for_foo_mixin, foo)
, cela devrait fonctionner.
Et je ne suis pas sûr que la conception de votre classe soit la bonne façon de le faire. Puisque vous utilisez un mixin pour implémenter bar
, il pourrait être préférable de ne pas dériver de foo et de simplement l'enregistrer avec la classe 'foo' (c'est-à-dire foo.register (myfoo)
) . Mais ce n’est que mon intuition.
Par souci d'exhaustivité, voici la documentation sur ABCs .
Autres conseils
Je pense (testé dans un cas similaire) que l'inversion des classes de base fonctionne:
class myfoo(bar_for_foo_mixin, foo):
def __init__(self):
print "myfoo __init__ called"
self.bar()
donc dans mro (), il trouverait une version concrète de bar () avant de trouver la version abstraite. Aucune idée si c'est ce qui se passe réellement en arrière-plan.
A bientôt, Lars
PS: le code qui a fonctionné dans Python 2.7 (python 3 utilise une méthode différente pour définir les métaclasses):
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()