2012-12-13 26 views
5

Ho conoscenza di Java e sto imparando C# per l'ultimo paio di giorni. Ora mi sono imbattuto nella parola chiave "virtuale" che, come suggerito allo this link, viene utilizzata per consentire che i metodi, le proprietà, ecc. Corrispondenti vengano sovrascritti nelle sottoclassi. Ora penso che possiamo sovrascrivere i metodi anche senza utilizzare la parola chiave "virtuale". Allora perché è necessario?parola chiave virtuale in C#

+4

"Ora penso che possiamo eseguire l'override dei metodi anche senza utilizzare la parola chiave 'virtuale'." Tu pensi? – BoltClock

+2

@BoltClock Certamente. 'abstract' nella classe base e' override' nella classe derivata sono sufficienti. Non c'è bisogno di 'virtuale': P – CodesInChaos

+1

Sì, virtuale significa" Sto fornendo un'implementazione, ma è possibile sovrascriverla in modo polimorfico "e astratta significa" Sto definendo qualcosa per cui devi fornire un'implementazione, che agirà polimorficamente ". A differenza dello shadowing (generalmente considerato non ottimale), le firme delle funzioni devono corrispondere. –

risposta

11

È necessaria la parola chiave virtual se si desidera realmente i metodi override nelle sottoclassi. In caso contrario, l'implementazione di base verrà nascosta dalla nuova implementazione, proprio come se fosse stata dichiarata con la parola chiave new.

Nascondere i metodi "sovrascrivendoli" senza il metodo di base dichiarato virtual lascia senza polimorfismo, ovvero: se si esegue il "cast" di una versione specializzata nella versione "base" e si chiama un metodo, sempre le classi di base l'implementazione verrà utilizzata al posto della versione sostituita, che non è quella che ci si aspetterebbe.

Esempio:

class A 
{ 
    public void Show() { Console.WriteLine("A"); } 
} 

class B : A 
{ 
    public void Show() { Console.WriteLine("B"); } 
} 

A a = new A(); 
B b = new B(); 

a.Show(); // "A" 
b.Show(); // "B" 

A a1 = b; 
a1.Show(); // "A"!!! 
2

Ora penso che possiamo eseguire l'override dei metodi anche senza utilizzare la parola chiave "virtuale".

No, non è possibile. Contrariamente a Java, in C# i membri sono sigillati per impostazione predefinita e non è possibile sovrascriverli a meno che non li abbia contrassegnati con la parola chiave virtual.

7

virtual è un modo per definire che un metodo ha un'implementazione predefinita,, ma che l'implementazione può essere sovrascritta in una classe figlio. Oltre all'uso virtuale, non è possibile sovrascrivere un metodo direttamente senza utilizzare la parola chiave new (che in genere è una cattiva pratica).

Un buon esempio dell'implementazione di virtual è il metodo ToString(). Ogni oggetto in C# può essere in grado di chiamare ToString() perché ogni oggetto eredita dalla classe System.Object di base, che contiene un metodo virtuale ToString(). Le classi derivate possono tuttavia prevalere su questa e fornire la propria implementazione che potrebbe essere più utile per gli utenti dell'oggetto.

Aggiornamento: Recentemente ho scritto un post sul blog che approfondisce questo argomento. Check it out here.

1

Date un'occhiata a questo esempio:

void Main() 
    { 
     var o1 = new S(); 
     Console.WriteLine(((B)o1).m1());  
    } 

    public class B 
    { 
     public virtual string m1() { 
      return "m1"; 
     } 
    } 

    public class S : B 
    { 
     override public string m1() { 
      return "overridden m1"; 
     } 
    } 

In questo esempio la sottoclasse S viene istanziato e assegnato alla oggetto variabile o1. Nel parametro della dichiarazione Console.WriteLine viene eseguito il cast nella classe base B, quindi viene chiamato il metodo m1. Perché abbiamo usato virtual nella classe base B e override nella sottoclasse S, stiamo ottenendo

m1 override

come output.Se si rimuove virtual nella dichiarazione metodo m1 in B e override nella sottoclasse S allora che stai ricevendo

m1

come uscita, il che significa che il cast ha anche l'effetto che la viene utilizzata la dichiarazione originale del metodo m1 nella classe base B.

N.B. Se si utilizza la parola chiave new in sottoclasse S, come ad esempio

  new public string m1() { 
      return "overridden m1"; 
     } 

supponendo che la parola chiave virtual nella classe di base B è assente, che stai ricevendo l'uscita

m1

pure. Se non lo volessi trasmettere a B, verrebbe utilizzato il nuovo metodo. Questo è chiamato ombreggiatura (o nascondendo) un metodo (il metodo originale della classe base).

Sommario:

  • Per ignorare un metodo, che dovrebbe essere efficace anche se si esegue il cast alla classe di base, utilizzare la parola chiave virtual nella classe base e override nella classe sub.

  • Se si desidera eseguire l'override del metodo, che dovrebbe essere attivo solo nella sottoclasse, utilizzare la parola chiave new nella dichiarazione del metodo delle sottoclassi. Come hai visto funziona anche senza di esso, ma è meglio se è lì così tutti sanno che questa è una nuova versione del metodo.