C'est le code que je prévois d'utiliser pour mon jeu. Mais il se plaint d'une erreur de MRO. Je ne sais pas pourquoi. Quelqu'un peut m'expliquer? Merci beaucoup.
class Player:
pass
class Enemy(Player):
pass
class GameObject(Player, Enemy):
pass
g = GameObject()
Votre GameObject
hérite de Player
et de Enemy
. Parce que Enemy
déjà hérite de Player
Python ne peut pas maintenant déterminer la classe sur laquelle rechercher les méthodes; Player
, ou sur Enemy
, qui remplacerait les éléments définis dans Player
.
Vous n'avez pas besoin de nommer toutes les classes de base de Enemy
ici; juste hériter de cette classe:
class GameObject(Enemy):
pass
Enemy
inclut déjà Player
, vous n'avez pas besoin de l'inclure à nouveau.
Je vais expliquer la raison pour laquelle le code d'origine ne fonctionne pas.
Python doit décider dans quel ordre chercher dans les classes de base (directes et indirectes) lors de la recherche d'un attribut/méthode d'instance. Pour ce faire, il linéarise le graphe d'héritage, c'est-à-dire qu'il convertit le graphe des classes de base en une séquence, à l'aide d'un algorithme appelé C3 ou MRO . L'algorithme MRO est l'unique algorithme qui réalise plusieurs propriétés souhaitables:
A
apparaissent toujours avant les enfants de la classe B
, alors A
devrait apparaître avant B
("ordre de priorité étendu cohérent")Avec votre code, la deuxième contrainte nécessite que Enemy
apparaisse en premier; la troisième contrainte nécessite que Player
apparaisse en premier. Comme il n’existe aucun moyen de satisfaire toutes les contraintes, python indique que votre hiérarchie d’héritage est illégale.
Votre code fonctionnera si vous changez l'ordre des classes de base dans GameObject
comme ceci:
class GameObject(Enemy, Player):
pass
Ce n'est pas juste un détail technique. Dans certains cas (espérons-le rares), vous voudrez peut-être déterminer quelle classe doit être utilisée pour récupérer la méthode que vous avez appelée si elle est définie dans plusieurs classes. L'ordre dans lequel vous définissez les classes de base affecte ce choix.
Ce que vous avez écrit, c'est que vous voulez que GameObject
soit à la fois Player
et Enemy
. Mais un Enemy
est déjà un Player
. Le problème de MRO indique simplement que si vous aviez un champ a
dans Player
, demander ce champ dans une instance GameObject
serait ambigu: ce devrait être le a
du premier Player
dont vous héritez ou celui du Player
que vous héritez via votre héritage Enemy
?
Mais êtes-vous sûr de ne pas vouloir utiliser la composition au lieu de l'héritage, ici?
class GameObject(object):
def __init__(self):
self.player = Player()
self.enemy = Enemy()