Ereditarietà OOP e costruttore predefinito

Supponiamo che ci sia una class base A e una class B derivata da A Quindi, sappiamo che il costruttore della class A non viene mai ereditato dalla class B Tuttavia, quando viene creato un nuovo object di B , allora – il costruttore predefinito della class A viene chiamato prima che venga invocato il costruttore predefinito / personalizzato della class B Forse lo scopo di questo è che i campi della class A devono essere inizializzati su valori predefiniti.

Supponiamo ora che la class A abbia definito un costruttore personalizzato. Ciò significa che il costruttore predefinito della class A viene rimosso silenziosamente dal compilatore. Ora, quando si crea una nuova istanza della class B , quale costruttore della class A viene chiamato automaticamente prima di invocare il costruttore della class B ? (In che modo i campi di class A vengono inizializzati in questo caso?)

Ora, quando si crea una nuova istanza della class B , quale costruttore della class A viene chiamato automaticamente prima di invocare il costruttore della class B ?

Il codice non riuscirà a compilare, in pratica. Ogni costruttore deve associare un altro costruttore, implicitamente o esplicitamente. Il costruttore su cui si incatena può essere nella stessa class (con this ) o nella class base (con base ).

Un costruttore come questo:

 public B() {} 

è implicitamente:

 public B() : base() {} 

… e se non si specifica affatto un costruttore, esso sarà implicitamente aggiunto allo stesso modo, ma deve ancora avere qualcosa da chiamare. Ad esempio, il tuo scenario:

 public class A { public A(int x) {} } public class B : A {} 

porta a un errore del compilatore di:

errore CS7036: Non c’è argomento dato che corrisponda al parametro formale richiesto 'x' di 'AA(int)'

Tuttavia, è ansible specificare una chiamata del costruttore diversa in modo esplicito, ad es

 public B() : base(10) {} // Chain to base class constructor 

o

 public B() : this(10) {} // Chain to same class constructor, assuming one exists 

Una volta fornito il proprio costruttore alla class A , durante la creazione dell’object di class B non si verificano invocazioni automatiche.

La prima riga nel costruttore della class B dovrebbe essere super(paramsToClassAConstructor) oppure può essere chiamata a un altro costruttore con nella class B usando this() . È responsabilità del secondo costruttore della class B chiamare il costruttore della class A in questo caso.

Quando un costruttore completa l’esecuzione, l’object si trova in uno stato iniziale valido. Dovremmo usare oggetti che sono validi.
Quando forniamo un costruttore non predefinito per la class A – stiamo dicendo in modo efficace – per build un object di class A cioè per essere nello stato iniziale valido – abbiamo bisogno di maggiori informazioni – che è fornito dai parametri.
Detto questo, il compilatore aiuta a non generare il costruttore predefinito. Il codice client non riuscirà a compilare (come dovrebbe – in quale altro modo renderemo l’object land in uno stato valido?) – e il programmatore client dovrebbe stare seduto e prendere nota.
Quando si fornisce un costruttore esplicito vuoto – si sta effettivamente dicendo al compilatore – So cosa sto facendo – il costruttore predefinito probabilmente inizializzerebbe i campi con alcuni valori predefiniti ragionevoli.
O per promuovere il riutilizzo: il costruttore predefinito può chiamare quello non predefinito con alcuni valori predefiniti.
Una sottoclass sa della sua super class – un costruttore di sottoclass può invocare metodi di super-class – (alcuni metodi comunemente riutilizzati nelle sottoclassi). Considerato quanto sopra, ciò richiede che la parte super-class debba essere in uno stato valido, ovvero che il suo costruttore sia stato eseguito prima di qualsiasi sua invocazione di metodo . Ciò richiede la chiamata del super costruttore prima del costruttore sottoclass.
Detto questo, sarai facilmente in grado di progettare il tuo costruttore per far rispettare il corretto comportamento dello stato iniziale .