2015-03-23 15 views

risposta

53

tuo GameObject eredita da PlayereEnemy. Perché Enemygià eredita da Player Python ora non è in grado di determinare quale classe guardare prima i metodi; Player o Enemy, che sostituisce le cose definite in Player.

Non è necessario denominare tutte le classi base di Enemy qui; solo eredita da quella classe:

class GameObject(Enemy): 
    pass 

Enemy include già Player, non è necessario includere di nuovo.

4

Quello che hai scritto è un GameObject sia uno Player sia uno Enemy. Ma uno Enemy è già un Player. La questione MRO afferma solo che se si ha un campo a in Player, chiedendo per questo campo in un'istanza GameObject sarebbe ambiguo: dovrebbe essere il a dal primo Player si eredita o quello dalla Player si eredita attraverso il vostro Enemy eredità ?

Ma sei sicuro di non voler utilizzare la composizione anziché l'ereditarietà, qui?

class GameObject(object): 
    def __init__(self): 
     self.player = Player() 
     self.enemy = Enemy() 
9

Spiegherò il motivo per cui il codice originale non funziona.

Python deve decidere in quale ordine cercare tra classi di base (dirette e indirette) durante la ricerca di un attributo/metodo di istanza. Lo fa linearizzando il grafico dell'ereditarietà, ovvero convertendo il grafico delle classi base in una sequenza, utilizzando un algoritmo chiamato C3 or MRO. L'algoritmo MRO è l'unico algoritmo che consente di ottenere diverse proprietà desiderabili:

  1. ogni classe antenato appare esattamente una volta
  2. una classe appare sempre prima della sua antenata ("monotonia")
  3. genitori diretti della stessa classe dovrebbe apparire nello stesso ordine in cui sono elencati nella definizione della classe ("consistente ordine di precedenza locale")
  4. se i bambini della classe A appaiono sempre prima che i bambini della classe B, quindi A dovrebbe comparire davanti B ("consistente ordine di precedenza esteso")

Con il proprio codice, il secondo vincolo richiede che venga visualizzato prima Enemy; il terzo vincolo richiede che venga visualizzato per primo Player. Poiché non c'è modo di soddisfare tutti i vincoli, python segnala che la gerarchia dell'ereditarietà è illegale.

Il codice funziona se si cambia l'ordine delle classi di base in GameObject in questo modo:

class GameObject(Enemy, Player): 
    pass 

Questo non è solo un dettaglio tecnico. In alcuni casi (si spera raramente), potresti voler pensare a quale classe dovrebbe essere usata per prendere il metodo che hai chiamato se il metodo è definito in più classi. L'ordine in cui vengono definite le classi di base influisce su questa scelta.

+2

Questa è una risposta molto migliore di quella accettata. –