2015-07-28 12 views
11

Ho il seguente codice.Perché assegniamo l'oggetto classe figlio alla variabile di riferimento della classe genitore?

public class Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    public new void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     Child C = new Child(); 
     C.Print(); 
    } 
} 

Se corro questo codice, ottengo il risultato "Metodo Child" Ma se lo faccio quanto segue, perché ottengo il risultato "Metodo Parent"?

public class Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    public new void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     Parent P = new Child(); // The only difference is this. 
     P.Print(); 
    } 
} 

L'unica differenza è la seguente

Child C = new Child(); 
Parent P = new Child(); 

ho pensato new Child() significa che creiamo l'istanza di Child di classe. E ho pensato entrambi, C e P, sono solo variabili di riferimento oggetto che contengono la posizione dell'istanza della classe Child.
Puoi correggermi se ho torto o dimmi se mi manca qualcosa perché non capisco perché nei casi sopra riportati ottengo risultati diversi?

+3

Poiché si sta nascondendo i metodi, non li override. Quando scrivi P.Print, il compilatore può solo chiamare il metodo di stampa dei genitori, non il metodo figlio nascosto. –

+0

Possibile duplicato: http://stackoverflow.com/questions/17717570/why-does-calling-a-method-in-my-derived-class-call-the-base-class-method –

+0

Come consiglio a parte, raccomando evitando di nascondere il metodo a meno che non ne abbiate legittimamente bisogno. Tende a rendere il codice più difficile da mantenere. Citando [Method Hiding Apologia] di Eric Lippert (http://blogs.msdn.com/b/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx), "Sembra che i tipi derivati ​​sembrino interrompere i contratti dei tipi di base Se un tipo derivato D nasconde un metodo M sulla classe base B perché DM fa qualcosa di diverso da BM, non dovrebbe avere un nome diverso? " – Brian

risposta

19

È perché hai rinviato il metodo Print a Child. Quindi, al momento della compilazione, P.Print() si risolve in Parent.Print, ma C.Print() si risolve in Child.Print(). Se tu avessi un metodo virtuale che era sovrascritti in Child invece, avevano entrambi stampa "Metodo Child":

public class Parent 
{ 
    // Declare this as virtual, allowing it to be overridden in 
    // derived classes. The implementation will depend on the 
    // execution-time type of the object it's called on. 
    public virtual void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    // Override Parent.Print, so if Print is called on a reference 
    // with compile-time type of Parent, but at execution it 
    // refers to a Child, this implementation will be executed. 
    public override void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

correlati:

0

Perché hai dichiarato che il tipo di P è Parent. Quando assegni a Child, verrà eseguito il cast per quel tipo.

4

dal momento che il 01 Il metodonon è virtual, il compilatore non emetterà il codice per indicare al CLR di richiamare il metodo in base al tipo di runtime effettivo.

Quindi, quando la variabile viene indicata come Child, verrà invocato il Child.Print. Ma, quando ti riferisci ad esso come Parent, verrebbe utilizzato Parent.Print.

L'utilizzo della parola chiave new qui si intende solo per shadowing, per dire al compilatore che il metodo bambino è davvero nasconde il metodo genitore e non override, ma non ha alcun effetto contrario.

1

JCronin, stai trasmettendo al genitore con padre P = nuovo figlio(). Per ottenere il comportamento della classe Child, devi ricondurlo a Child (var x = (Child) P) o creare l'istanza dell'istanza Child (Child P = new Child()).

Vedi Downcasting

8

Ecco ciò che accade sotto il cofano

Child C = new Child(); 
C.Print(); 

Poiché si sta nascondendo i metodi, non li override. quindi il metodo Print in Parent è nascosto e viene richiamato Child.Print().

enter image description here

Parent P = new Child(); // The only difference is this. 
P.Print(); 

Questo (New sitter()) saranno chiamati su un tipo di genitore di riferimento.

enter image description here

se si tenta questo, tipo genitore di riferimento sarà colato al tipo di bambino. D'ora in poi Child.Print() è invocato.

Parent P = new Child(); 
((Child)P).Print(); 

enter image description here

uscita sarà: Bambino Metodo

+0

Grazie per la risposta, ma potresti dirmi cosa sono ?? – JCronin

+0

@JCronin sono CIL. CIL è un linguaggio di basso livello. fondamentalmente quando si compila il codice, verrà compilato in linguaggio intermedio (IL), viene anche chiamato MSIL (Microsoft Intermediate Language). è possibile visualizzare il codice IL utilizzando https://msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.110).aspx BTW, ho usato LINQPad per ottenere il codice IL. puoi controllare qui https://www.linqpad.net/ – yantaq

Problemi correlati