在以下C#代码段
中public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal sound");
}
}
public class Dog:Animal
{
public override void MakeSound()
{
Console.WriteLine("Dog sound");
}
}
class Program
{
static void Main(string[] args)
{
Animal an = new Dog();
an.MakeSound();
Console.ReadLine();
}
}
要调用的方法是在运行时确定的。为什么编译器确切无法弄清楚,调用哪种方法?
为什么编译器不会看到an
引用Dog
对象然后从该类中选择方法?
运行时如何确定调用哪个方法?
答案 0 :(得分:3)
这听起来很像考试/家庭作业问题。但是,让我用另一个问题回答你的问题。 请考虑以下代码:
static void Main(string[] args)
{
var random = new Random();
Animal an = null;
if (random.NextDouble() < 0.5) {
an = new Dog();
} else {
an = new Cat();
}
an.MakeSound();
Console.ReadLine();
}
编译器如何知道在编译时调用哪种方法?它不能,仅在运行时是已知的具体类型。
答案 1 :(得分:0)
你告诉compilier这个变量属于Animal类型。它只查看声明,而您希望它执行您的代码以弄清楚您的意思。这不是它的工作原理。
答案 2 :(得分:0)
请考虑以下代码:
class Program
{
static void Main(string[] args)
{
Animal dog = new Dog();
MakeSoundAbstract(dog);
Animal an = new Animal();
MakeSoundAbstract(an);
Console.ReadLine();
}
static void MakeSoundAbstract(Animal animal)
{
animal.MakeSound();
}
}
如果编译器将在编译期间确定虚拟调用而不是在运行时期间,那么MakeSoundAbstract
方法将始终执行MakeSound
class Animal
方法,因此我们将失去https://technet.microsoft.com/en-us/library/ms173248%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396的强大功能。
答案 3 :(得分:0)
考虑对您的代码进行此更改:
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Animal sound");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof!");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Purrrrrrrrrrrrrr");
}
}
class Program
{
static void Main(string[] args)
{
Animal an = GetAnimal(DateTime.Now);
an.MakeSound();
Console.ReadLine();
}
private Animal GetAnimal(DateTime dateTime)
{
if (dateTime.DayOfWeek == DayOfWeek.Monday)
{
return new Dog();
}
else
{
return new Cat();
}
}
}
现在无法知道在编译时要创建什么类型的动物,因为它取决于代码实际运行的星期几。星期一你会得到一只狗,但在任何时候你都会得到一只猫。这是多态的一个定义好处 - 类型不是由编译器烘焙的,而是在代码执行时动态派生的。多态性允许您使用这些派生类型,即使您在编写代码时并不确切知道它们是什么(但您确实知道它们是所有类型的动物)。