2010-03-05 15 views
14

Diciamo che ho class, che utilizza alcune funzionalità di dict. Ho usato per comporre un oggetto dict all'interno e fornire un accesso dall'esterno, ma recentemente ho pensato di ereditare semplicemente dict e aggiungere alcuni attributi e metodi che potrei richiedere. È un buon modo per andare o dovrei attenermi alla composizione?python: ereditario o composizione

risposta

13

L'ereditarietà è molto spesso abusata. A meno che la tua classe non sia destinata ad essere usata come dizionario generico con funzionalità extra, direi che la composizione è la strada da percorrere.

Salvare le chiamate di inoltro di solito non è un motivo sufficiente per scegliere l'ereditarietà.

Dal libro Design Pattern:

favore composizione di oggetti nel corso di ereditarietà di classe

Idealmente non dovrebbe avere per creare nuovi componenti per raggiungere il riutilizzo. È necessario che sia in grado di ottenere tutte le funzionalità di necessarie assemblando i componenti esistenti tramite la composizione dell'oggetto . Ma raramente è il caso , perché il set di componenti disponibili non è mai abbastanza abbastanza nella pratica. Il riutilizzo per eredità semplifica la creazione di nuovi componenti che possono essere composti con quelli vecchi. La successione e la composizione dell'oggetto funzionano quindi insieme.

Tuttavia, la nostra esperienza è che i progettisti eredità un uso eccessivo come tecnica di riutilizzo e disegni sono spesso reso più riutilizzabili (e più semplice) da seconda più composizione di oggetti."

L'intero testo è qui: http://blog.platinumsolutions.com/node/129

+3

Ricorda che Python è estremamente flessibile, la composizione degli oggetti è ottima, ma se stai solo mappando uno a uno su un altro oggetto, l'ereditarietà è la strada da percorrere. – voyager

+3

Non penso che abbia nulla a che fare con la flessibilità di Python, è un problema di design. Se stai mappando tutti i metodi di un oggetto all'altro, probabilmente stai costruendo un dizionario: usa l'ereditarietà. Ma quando il poster originale scrive "I have class, that utilizza alcune funzionalità di dict", allude al fatto che la classe non è pensata per essere usata come un dizionario. –

+0

Il link a platinumsolutions non funziona più ... potresti modificare ... – unclejamil

3

Entrambi sono buoni, ma preferirei ereditare, poiché significherebbe meno codice (che è sempre buono fintanto che è leggibile).

Dive into Python has a very relevant example.

Su Python 2.2 e versioni precedenti, non è stato possibile creare sottoclassi da ins integrati direttamente, pertanto ha avuto per utilizzare la composizione.

class FileInfo(dict):     
    "store file metadata" 
    def __init__(self, filename=None): 
     self["name"] = filename 
  1. La prima differenza è che non c'è bisogno di importare il modulo UserDict, dal momento che dict è un built-in tipo di dati ed è sempre disponibile. Il secondo è che si eredita direttamente da dict, invece che da UserDict.UserDict.
  2. La terza differenza è sottile ma importante. A causa del modo in cui UserDict funziona internamente, è necessario chiamare manualmente il suo metodo __init__ per inizializzare correttamente le sue strutture dati interne. dict non funziona così; non è un wrapper e non richiede l'inizializzazione esplicita.
3

È veramente a pesare il costo e la portata di ciò che si sta cercando di fare Ereditando da dict perché si vuole un comportamento simile ai dizionari è veloce. e facile, ma soggetto a limitazioni come la creazione di oggetti creati dalla classe per essere inascoltabili

Quindi, ad esempio, se si desidera serializzare (ovvero pickle) gli oggetti, ma anche il comportamento di tipo dizionario, quindi ovviamente non puoi ereditare direttamente da dict e avrai bisogno di comporre le parti della funzionalità che desideri per farlo accadere.

3

Se isinstance(my_object, dict) restituisce Vero o Falso? In altre parole, se accidentalmente assegnate uno degli oggetti a qualcosa che desidera un dict, dovrebbe cercare di utilizzarlo allegramente come dict? Probabilmente no, quindi usa la composizione.

+0

Aiutare la gente a digitare tipografia non è necessariamente una buona cosa. –

+0

Il controllo del tipo ha la sua posizione. Ad esempio, se avessi una bella funzione di stampa che comprendeva dict, probabilmente non vorresti che stampasse il tuo oggetto avanzato come se fosse un ditt. Né vorresti usare l'alternativa di tipo check-free: monkey patching dict. –