2016-04-27 120 views
0

在下面的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

你有没有听说过抽象? –

+0

我说狗的声音,如果我编译它,这对我来说似乎是完全不错的 – BugFinder

+0

他们没有问在运行时的输出是什么。事实上,他们在实际问题中明确表示他们知道运行时正在发生的事情。问题是为什么编译器不知道'an'是编译时的'Dog'。 – Nick

回答

0

你告诉编译器该变量是Animal类型的。它只看到声明,而你期望它执行你的代码来找出你的意思。这不是它的工作原理。

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(); 
} 

如何编译器应该在编译时知道哪种方法来调用?它不能,只有在运行时才会知道具体的类型。

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方法将总是执行class Animal所以我们正在失去这里的abstraction功率MakeSound方法。

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(); 
    } 
    } 
} 

现在是不可能知道要创建什么类型的动物在编译时间,因为它取决于星期的代码时实际运行。星期一你会得到一只狗,但在任何时候你会得到一只猫。这是多态性的一个明显的好处 - 类型不是由编译器烘焙的,而是在代码执行时即时导出的。多态性允许您使用这些派生类型,即使您在编写代码时(但您确实知道它们都是所有类型的动物)并不确切知道它们会是什么。

相关问题