Siamo spiacenti, ma si sbaglia completamente; questo andrebbe contro l'intero punto dei metodi virtuali. Se someObject
è un A
, verrà invocato il numero A.MyMethod
. Se someObject
è un B
, verrà richiamato lo B.MyMethod
. Se someObject
è un BaseClass
e non un'istanza di un tipo derivata da BaseClass
, verrà richiamato lo BaseClass.MyMethod
.
Usiamo esempio preferito da tutti:
class Animal {
public virtual void Speak() {
Console.WriteLine("i can haz cheezburger?");
}
}
class Feeder {
public void Feed(Animal animal) { animal.Speak(); }
}
class Cat : Animal {
public override void Speak() { Console.WriteLine("Meow!"); }
}
class Dog : Animal {
public override void Speak() { Console.WriteLine("Woof!"); }
}
Poi:
Animal a = new Animal();
Animal c = new Cat();
Animal d = new Dog();
Feeder f = new Feeder();
f.Feed(a);
f.Feed(c);
f.Feed(d);
questo stampa:
i can haz cheezburger?
Meow!
Woof!
Ancora una volta, questo è l'intero punto di metodi virtuali.
Inoltre, possiamo andare alle specifiche. Da 10.6.3 (metodi virtuali)
In una chiamata di metodo virtuale, il tipo run-time dell'istanza per cui tale invocazione avviene determina l'effettiva attuazione metodo da chiamare.
(grassetto e corsivo nell'originale.)
In termini precisi, quando un metodo denominato N
viene richiamato con una lista di argomenti A
in un'istanza con un tipo in fase di compilazione C
e un tipo run-time R
(dove R
è o C
o una classe derivata da C
), l'invocazione viene elaborato come segue:
• Innanzitutto, risoluzione di sovraccarico viene applicato a C
, N
e A
, selezionare un metodo specifico M
dal set di metodi dichiarati e ereditato da C
. Questo è descritto in § 7.5.5.1.
• Quindi, se M
è un metodo non virtuale, viene richiamato M
.
• Altrimenti, M
è un metodo virtuale e viene richiamata l'implementazione più derivata di M
rispetto a R.
(Bolding non in originale.)
Poi, abbiamo bisogno della definizione di "implementazione con massima derivazione di M
." Questa è una bella definizione ricorsiva:
L'implementazione con massima derivazione di un metodo virtuale M
rispetto ad una classe R
è determinato come segue:
• Se R
contiene la dichiarazione virtuale introduzione di M
, allora questo è l'implementazione più derivata di M
.
• In caso contrario, se R
contiene un override di M
, questa è l'implementazione più derivata di M
.
• Altrimenti, l'implementazione più derivati M
rispetto R
è lo stesso come l'implementazione con massima derivazione di M
rispetto alla classe base diretta di R
.
Pertanto, nell'esempio di cui sopra con Cat : Animal
e Dog : Animal
, quando il parametro a
a Feeder.Feed(Animal)
è un'istanza di Cat
poi Cat.Speak
è l'implementazione con massima derivazione. Questo è il motivo per cui vedremo "Meow!
" e non "i can haz cheezburger?
"
Questo è un odore di codice. – Will
Qual è il tipo di oggetto ACTUAL che si sta passando al costruttore AnotherObject? In altre parole, qual è la nuova affermazione? Perché quello che stai descrivendo può succedere solo se hai una BaseClass nuova invece di una A o una B. – Nick
Penso che il fatto che sia un odore di codice sia ovvio per David altrimenti la domanda non sarebbe stata postata e il codice puzzolente avrebbe è stato usato invece. – Greg