2015-02-01 10 views
7

Descrizione problema: Ho una classe C che eredita da mixin A e B. Desidero una nuova classe, C_, con tutti i metodi/attributi definiti nella classe C ma con B scambiato con B_ (stessa API) nello schema di ereditarietà (un possibile utilizzo di questo è semplice simulazione). Tutte le classi sono nuove classi di stile.È OK usare l'MRO per scavalcare un mix?

ho ottenuto quello che volevo da scherzi con l'ordine di ereditarietà, quindi la MRO:

A B B_ B_ A B 
\//  \ \/
    C /  \ C 
    \/   \/
    C1   C2 
C1(C,B_)  C2(B_,C) 

C1.__mro__ = (C1, C , A, B, B_, object) 
C2.__mro__ = (C2, B_, C, A, B , object) 

Il metodo C2 (ereditando il mixin modificato prima della classe C) funziona senza molta sorpresa e se io chiamo un metodo definito nel mix B, viene scelta la definizione di B_.

Per il momento funziona, ma mi sento come: "dita incrociate, spero che un caso speciale non si presenti e rompere il sistema!"

La domanda è: è un modo finalmente non così sbagliato per risolvere il problema o esiste un modo migliore per farlo?

PS: Penso che potrei prendere il mio bazooka e creare una metaclasse per ridefinire il mro (as said in the official doc), ma il mio istinto dice che non sarà necessariamente più carina.

+1

Non vedo niente di sbagliato con esso. L'algoritmo utilizzato per costruire l'MRO è documentato e, come tale, puoi fare affidamento sull'ordine che stai vedendo. – Bakuriu

+0

Nota: se B_ eredita da B, precede B nell'MRO qualunque sia l'ordine nella definizione della classe. Questo non è il tuo caso d'uso, ma potrebbe essere il caso di qualcuno che sta cercando su questo, quindi ho pensato che potesse valere la pena menzionarlo. Posso capire perché B_ non erediterebbe da B ma nota che non sostituisci esattamente B con B_: i metodi definiti in B e non in B_ sono ancora presi da B. –

risposta

0

Sai già che questo è disordinato. Se A e B (e quindi B ') dovessero avere attributi in comune, allora C otterrebbe quegli attributi da A mentre C_ li otterrebbe da B_.

Supponendo che non si utilizza super() in tutti i nuovi metodi definiti in C, vorrei fare una semplice C Class (senza basi) e poi scrivere

class D(C, A, B): pass 
class D_(C, A, B_): pass