0

我对 C# 很陌生,所以我希望如果我的问题听起来很愚蠢,请原谅我的无知。

-我正在尝试Inheritance使用 FundaC#并发现它的行为方式有些奇怪,所以我想用 来检查它Java,我得到了预期的结果。

-我只想知道这里有什么我想念的......

C#代码:

 class Animal
 {
   public void Sound()
   {
     System.Console.WriteLine("I don't make any sound");
   }


 } 





 class Dog : Animal
 {
   public void Sound()
   {
     System.Console.WriteLine("barking");


   }  

 }


 class InheritTest
 {
   static void Main()
   {
     Animal a = new Dog();         // Implicit conversion

     Dog    d = (Dog) a;   // Explicit conversion


     a.Sound();
     d.Sound();

   }

 }

输出 :

I don't make any sound
barking

JAVA代码:

 class Animal
 {
   public void sound()
   {
     System.out.println("I don't make any sound");
   }


 } 





 class Dog extends Animal
 {
   public void sound()
   {
     System.out.println("barking");


   }  

 }


 class InheritTest
 {
   public static void main(String[] args)
   {
     Animal a = new Dog();         // Implicit conversion

     Dog    d = (Dog) a;   // Explicit conversion


     a.sound();
     d.sound();

   }

 }

输出 :

barking
barking

-现在我对这一整集的怀疑是..在C#我分配给类型Dog object的对象引用变量时,然后当我调用方法时,我应该得到输出(这是 Dog 类中的重写方法),而是方法称为将输出作为。aAnimalSound()abarkingAnimal's Sound()I don't make any sound

-但是Java事情按预期工作..继承在任何地方都以相同的方式工作,所以我哪里出错了。

如果有人可以帮助我,我将不胜感激......在此先感谢。

4

3 回答 3

5

在您的第一个示例中,您实际上并没有覆盖现有方法 - 您正在隐藏它。它是一种特殊的 C# 机制,不同于传统的方法覆盖。将源方法标记为virtual并覆盖方法override,使其按预期工作。这是一个很好的解释。你没有收到警告吗?

于 2014-05-05T05:39:34.293 回答
3

默认情况下,方法virtual在 Java (IIRC) 中。在 C# 中,情况并非如此。

将您的 C# 方法标记为virtualoverride它们。这将产生预期的输出。

于 2014-05-05T05:40:56.793 回答
0

考虑代码

Animal a = new Dog();
a.sound();

为了调用 sound 方法,运行时需要先解析对象(Dog)的实际类型,然后在其上调用 sound 方法。如果方法(声音)在类型(Dog)上不存在,则需要调用编译时类型(Animal)上的方法。

如您所见,此过程可能需要一段时间并且会影响性​​能。为了使这个过程更高效,C# 使用了一种叫做“虚拟表”的东西,而 Java 使用了一种叫做运行时“动态调度”的技术。这意味着在 C# 中,我们需要将方法标记为虚拟,以告诉编译器它需要对底层类型执行查找。与每个对象都必须检查需要调用哪个实际方法相比,这样程序消耗的内存要少得多,并且执行得更快。但是,这也意味着现在每个方法都需要标记为虚拟,以告诉编译器我们需要一个虚拟表来查找该方法。

总而言之,就是设计理念的不同。Java 使程序员可以更轻松地扩展类,而无需担心将哪些函数标记为虚拟,方法是将所有函数默认设置为虚拟。另一方面,当您希望在派生类中重写功能时,C# 要求您将功能标记为虚拟。这也有助于消除无意中覆盖基类的功能。(在基类中的 C# 方法需要标记为虚拟并在派生类中覆盖)

于 2014-05-05T06:21:22.080 回答