Извините, но вы полностью ошибаетесь;это пошло бы против всей сути виртуальных методов.Если someObject
является A
, то будет вызываться A.MyMethod
.Если someObject
является B
, то будет вызываться B.MyMethod
.Если someObject
является BaseClass
и не является экземпляром типа, производного от BaseClass
, то будет вызываться BaseClass.MyMethod
.
Давайте воспользуемся всеми любимым примером:
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!"); }
}
Тогда:
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);
Это напечатает:
i can haz cheezburger?
Meow!
Woof!
Опять же, в этом весь смысл виртуальных методов.
Далее мы можем перейти к спецификации.Начиная с 10.6.3 (Виртуальные методы)
При вызове виртуального метода тип времени выполнения экземпляра, для которого выполняется этот вызов, определяетфактическая реализация метода для вызова.
(жирный и курсив в оригинале.)
В точном выражении, когда метод с именем N
вызывается со списком аргументов A
в экземпляре стип времени компиляции C
и тип времени выполнения R
(где R
равен либо C
или классу, производному от C
), вызов обрабатывается следующим образом:
• Сначала разрешение перегрузки применяется к C
, N
и A
, чтобы выбрать конкретный метод M
из набора методов, объявленных и унаследованных C
.Это описано в §7.5.5.1.
• Затем, если M
является не виртуальным методом, вызывается M
.
• В противном случае, M
является виртуальным методом, и вызывается наиболее производная реализация M
по отношению к R.
(жирный шрифт не в оригинале.)
Затем нам нужноопределение «наиболее производная реализация M
».Это хорошее рекурсивное определение:
Наиболее производная реализация виртуального метода M
относительно класса R
определяется следующим образом:
• Если R
содержит вводное виртуальное объявление M
, то это наиболее производная реализация M
.
• В противном случае, если R
содержит переопределение M
, то это наиболее производноереализация M
.
• В остальном, наиболее производная реализация M
относительно R
совпадает с самой производной реализацией M
относительно прямого базового класса R
.
Таким образом, в нашем примере выше с Cat : Animal
и Dog : Animal
, когда параметр a
до Feeder.Feed(Animal)
является экземпляром Cat
, тогда Cat.Speak
являетсянаиболее производная реализация.Вот почему мы увидим «Meow!
», а не «i can haz cheezburger?
»