Este es el código que planeo usar para mi juego. Pero se queja por un error de MRO. No se por que ¿Puede alguien explicarme por mí? Muchas gracias.
class Player: pass class Enemy(Player): pass class GameObject(Player, Enemy): pass g = GameObject()
Tu GameObject
está heredando de Player
y Enemy
. Debido a que Enemy
ya hereda de Player
Python ahora no puede determinar qué clase buscar primero en los métodos; ya sea Player
, o en Enemy
, que anularía las cosas definidas en Player
.
No necesitas nombrar todas las clases base de Enemy
aquí; simplemente heredar de esa clase:
class GameObject(Enemy): pass
Enemy
ya incluye Player
, no necesitas incluirlo de nuevo.
Explicaré la razón por la que el código original no funciona.
Python debe decidir en qué orden buscar las clases base (directas e indirectas) al buscar un atributo / método de instancia. Lo hace linealizando el gráfico de herencia, es decir, convirtiendo el gráfico de clases base en una secuencia, utilizando un algoritmo llamado C3 o MRO . El algoritmo MRO es el algoritmo único que logra varias propiedades deseables:
A
siempre aparecen antes que los hijos de clase B
, entonces A
debería aparecer antes de B
(“orden de prioridad extendido consistente”) Con tu código, la segunda restricción requiere que aparezca Enemy
primero; la tercera restricción requiere que el Player
aparezca primero. Como no hay forma de satisfacer todas las restricciones, Python informa que su jerarquía de herencia es ilegal.
Tu código funcionará si GameObject
el orden de las clases base en GameObject
así:
class GameObject(Enemy, Player): pass
Esto no es sólo un detalle técnico. En algunos casos (con suerte raros), es posible que desee pensar qué clase debería usarse para tomar el método al que llamó si el método está definido en varias clases. El orden en que se definen las clases base afecta esta elección.
Lo que escribiste es que quieres que un GameObject
sea tanto un Player
como un Enemy
. Pero un Enemy
ya es un Player
. El problema de MRO simplemente indica que si tuvieras un campo en Player
, pedir este campo en una instancia de GameObject
sería ambiguo: si fuera el nombre del primer Player
que heredas o el del Player
que heredas a través de tu herencia Enemy
?
Pero, ¿estás seguro de que no quieres usar la composición en lugar de la herencia aquí?
class GameObject(object): def __init__(self): self.player = Player() self.enemy = Enemy()