2009-03-26 18 views
5

Quando ho iniziato a lavorare con i linguaggi di programmazione orientati agli oggetti, mi è stato insegnato la seguente regola:Perché le variabili membro dovrebbero essere inizializzate nei costruttori?

Quando si dichiara un campo in una classe, non inizializzare ancora. Fallo nel costruttore.

Un esempio in C#:

public class Test 
{ 
    private List<String> l; 

    public Test() 
    { 
     l = new List<String>(); 
    } 
} 

Ma quando qualcuno recentemente mi ha chiesto il motivo per cui a farlo, non ho potuto trovare una ragione. Non ho molta familiarità con il funzionamento interno di C# (o altri linguaggi di programmazione, per quanto mi riguarda, poiché credo che ciò possa essere fatto in tutte le lingue OO).

Quindi perché è questo fatto? È sicurezza? Proprietà?

risposta

14
  • Se si dispone di più costruttori, si potrebbe desiderare di inizializzare un campo per valori diversi

  • Quando si inizializza il campo nel costruttore, non ci può essere confusione su quando esattamente viene inizializzato per quanto riguarda al resto del costruttore. Questo può sembrare banale con una singola classe, ma non così tanto quando si ha una gerarchia di ereditarietà con il codice costruttore in esecuzione ad ogni livello e l'accesso ai campi della superclasse.

10

Il compilatore C# prenderà qualsiasi intializzazione di membro non statico che si esegue in linea e spostandolo nel costruttore per conto dell'utente. In altre parole questo:

class Test 
{ 
    Object o = new Object(); 
} 

viene compilato a questo:

class Test 
{ 
    Object o; 

    public Test() 
    { 
     this.o = new Object(); 
    } 
} 

io non sono sicuro di come compilatori per altri linguaggi di gestire questo, ma per quanto riguarda C# è interessato è una questione di stile e si sono liberi di fare qualunque cosa tu voglia. Si noti che i campi statici vengono gestiti in modo diverso:read this article for more information on that.

1

a volte il costruttore ha parametri che vengono utilizzati per inizializzare le variabili interne. Ad esempio, dimensione delle matrici

2

Un motivo per farlo è che inserisce tutto il codice di inizializzazione in un posto che è conveniente per gli altri che leggono la classe. Detto questo, non lo faccio per due motivi principali. (1) Uso il test TDD/unità per definire il comportamento della mia classe. Se vuoi sapere cosa fa il costruttore senza parametri, dovresti davvero leggere i test che ho costruito sul costruttore senza parametri. (2) Con C# 3.0, in genere utilizzo le proprietà automatiche e l'inizializzazione inline con un costruttore senza parametri per istanziare l'oggetto. Questo è molto più flessibile e mette la definizione delle proprietà esattamente nella riga in cui viene utilizzato il codice. Ciò sovrascriverebbe qualsiasi inizializzazione nel costruttore, quindi raramente li inserisco. Naturalmente, questo vale solo per C#.

Es. (di 2)

var foo = new Foo { Bar = "baz" }; 

    public class Foo 
    { 
     public string Bar { get; set; } 

     public Foo() { } 
    } 
0

Non ho sentito un motivo convincente per non offrire entrambe le opzioni. Sospetto che la vera ragione abbia a che fare con la semplificazione della struttura linguistica da una prospettiva di analisi.Ciò è particolarmente vero nei linguaggi derivati ​​da C in cui l'analisi di un'istruzione di assegnazione richiede il 75% delle regole di sintassi della lingua. Mi sembra che accettarlo e definire come funzionerebbe con precisione sarebbe bello. Sono d'accordo con Michael's comment sull'aumento della complessità quando si inseriscono l'ereditarietà e più costruttori, ma solo perché si aggiunge una funzionalità non significa che è necessario utilizzarla. Voterò per sostenere entrambi, anche se il mio voto non contribuisce molto.

0

Mi piace sempre pensare alla classe come a una fabbrica di oggetti e al costruttore come all'ultima tappa della linea di produzione. I campi dichiarati nella classe sono schemi che descrivono l'oggetto, ma il progetto non verrà realizzato in un oggetto prima che tale oggetto sia ordinato tramite una chiamata al costruttore ... Inoltre, come qualcuno ha sottolineato, facendo tutte le tue inizializzazioni in il tuo costruttore migliorerà la leggibilità, oltre a garantire dinamicità nell'inizializzazione (potrebbe non essere un costruttore senza parametri con cui hai a che fare).

Inoltre, in alcune lingue il costruttore può essere utilizzato per reimpostare un oggetto in uno stato originale, motivo per cui sarà quindi necessario instaziare l'oggetto nel costruttore.

Problemi correlati