2016-02-25 6 views
5

Ho semplici tre classi:Nuova parola chiave: perché il metodo derivato non viene chiamato?

class A 
{ 
    public virtual void Write() 
    { 
     Console.Write("A"); 
    } 
} 

class B:A 
{ 
    public override void Write() 
    { 
     Console.Write("B"); 
    } 
} 

class C : B 
{ 
    public new void Write() 
    { 
     Console.Write("C"); 
    } 
} 

E io sono la creazione di oggetti e chiamando i loro metodi:

A a = new A(); 
a.Write(); 

A b = new C(); 
b.Write(); 

C c = new C(); 
c.Write(); 

E uscita sarà: ABC

Quello che non riesco a capire è motivo per cui questi il codice produce B?:

A b = new C(); 
b.Write(); 

ho pensato che dovrebbe essere C. Tuttavia, ho provato molte volte, ed è sempre B.

Capisco che A b = new C() crei un nuovo tipo di oggetto di C. Quindi l'output dovrebbe essere C. Oppure è un comportamento speciale chiamare il metodo sovrascritto quando lo usiamo senza il cast?

Perché succede? Poiché non abbiamo utilizzato alcun riferimento alla classe B.

+5

Perché è così che funziona la nuova parola chiave. https://msdn.microsoft.com/en-us/library/ms173153.aspx – AndyJ

risposta

6

Funzionerebbe se devi usare ((C)b).Write();

Con la parola new non sei l'override del metodo Write per C, ma piuttosto la creazione di un nuovo metodo definito solo per C. Quindi per la vostra C in realtà avete 2 metodi con un nome di metodo Write.

A c = new C(); 

c.Write();   //Output "B", you're calling the overridden method  
((C)c).Write();  //Output "C", you're calling the method defined on C 

//or 

(c as C).Write(); 

Lo stesso accade quando si definirebbe c come C:

C c = new C(); 

c.Write();   //Output "C"  
((A)c).Write();  //Output "B" 

Nel primo esempio si sta chiamando il nuovo metodo definito su C. Nella seconda riga si sta chiamando il metodo Write da A, che è sovrascritto da B, quindi l'uscita "B".

Edit: (un po 'di spiegazioni)

variabile c è di tipo A, ed è quello che il compilatore sa "c è un'istanza di A", non si sa che in realtà è di un tipo più derivato. Quando chiami il metodo Write su di esso, invocherà il metodo definito su A (che è sovrascritto da B). La tua classe base A non ha alcuna conoscenza del tuo nuovo metodo definito su C (questo è ciò che fa new, crea un nuovo metodo), quindi a meno che non lo lanci in C per far conoscere al compilatore il tipo effettivo derivato di c, il metodo di la tua classe base sarà chiamata.

+1

Spesso chiamato "nascondere il membro" o "shadowing", usarlo con parsimonia e attenzione - può essere piuttosto fastidioso quando ti aspetti che il codice faccia qualcosa altro. –

+0

Mi dispiace per la mia domanda stupida, ma perché questi codici 'A b = new C(); b.Write(); 'chiama il metodo overriden? Voglio dire che 'A b = new C()' crea un nuovo tipo di oggetto di 'C'. Quindi l'output dovrebbe essere 'C'. Oppure è un comportamento speciale chiamare il metodo sovrascritto quando lo usiamo senza il casting? – StepUp

+0

Per accedere a un metodo che ne nasconde un altro, è necessario un riferimento fortemente tipizzato al tipo che definisce il nascondiglio, non un riferimento di base. La stessa regola si applica anche alle interfacce esplicitamente implementate.Non è fondamentalmente un'eredità "corretta", quindi la gerarchia dell'ereditarietà non viene applicata allo stesso modo di una chiamata di metodo sovrascritta standard. –