2010-10-04 18 views
5

Nell'ereditarietà perché il costruttore della classe base riceve prima la chiamata, perché non quella derivata ??Perché il costruttore viene chiamato nell'ordine inverso?

+2

Vedere: http://stackoverflow.com/questions/140490/base-constructor-in-c-which-gets-called-first, http://stackoverflow.com/questions/1882692/c-constructor-execution -ordine –

risposta

7

Per assicurarsi che i membri pubblici o protetti della classe base siano correttamente inizializzati prima di essere utilizzati nella classe derivata.
Per essere precisi, il costruttore della classe derivata viene eseguito prima con una chiamata implicita al costruttore della classe base inserito come prima istruzione nel corpo del costruttore della classe derivata dal compilatore (assumendo i costruttori no-arg predefiniti).

3

La classe derivata viene creata estendendo la classe base. È necessario assicurarsi che i membri della classe base siano inizializzati correttamente, prima che possano essere estesi in una classe derivata. Inoltre, i membri inizializzati nella classe derivata non devono essere sovrascritti dalla classe base.

2

Che cosa nasce prima, il genitore o il bambino?

3

Considerate cosa potrebbe accadere se fosse il contrario. Immaginiamo una classe utente con un valore _id. Lo _id di 0 è un valore speciale che rappresenta un account "guest" (ignora i problemi relativi ai "valori speciali", in primo luogo non sono sempre una cattiva idea, e in secondo luogo questo è solo un esempio). Il _id non può anche essere modificato dopo la costruzione (il che ha senso, se può essere cambiato non è più un identificatore).

public class User 
{ 
    private readonly int _id; 
    public User(int id) 
    { 
    _id = id; 
    } 
    public int ID 
    { 
    get { return _id; } 
    } 
    public bool IsGuest 
    { 
    get { return _id == 0; } 
    } 
} 

Considerare ora una classe di amministrazione che sottoclassi da questo. Una delle regole della classe Admin è che un guest non può mai essere un amministratore. Questo invariante dovrebbe essere applicata in tutti i punti dello stato ospite può cambiare, che in questo caso è solo nel costruttore:

public class Admin : User 
{ 
    public Admin(int id) 
    :base(id) 
    { 
    if(IsGuest) 
     throw new SecurityException("Guest users cannot be admins."); 
    } 
} 

Se Admin è stato costruito prima del User allora sarebbe sempre buttare questa eccezione, come il test sarebbe sempre confronta 0 con 0. Se avessimo un valore speciale diverso per gli ospiti, sarebbe anche peggio, e non lanciare mai l'eccezione anche quando dovrebbe, e consentire un problema di sicurezza.

Tenere presente anche che la persona che scrive la classe Admin non deve avere alcuna conoscenza di come User funzioni oltre quanto documentato sulla sua interfaccia pubblica e protetta. Potrebbero captare il problema sopra aggiungendo il proprio test per verificare se id è zero o no, ma a parte il fatto che si tratta di una inutile duplicazione del codice, non c'è motivo per cui debbano sapere come funziona il controllo IsGuest, e potrebbe essere molto più complicato che è sopra, e forse forse proprietario, offuscato e non documentato.

Più in generale, l'intero concetto di "costruzione di un amministratore" non ha senso senza il concetto di "costruzione di un utente" come qualcosa che è accaduto per prima, non possiamo creare un tipo più specializzato di X senza creare una X come un prerequisito.

Problemi correlati