【问题标题】:Wierd behaviour with Inheritance in C#C#中继承的奇怪行为
【发布时间】:2014-05-05 05:37:06
【问题描述】:

我是 C# 的新手,所以如果我的问题听起来很愚蠢,请原谅我的无知。

- 我在尝试Inheritancefunda 和C#,发现它的行为有些奇怪,所以我想用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 分配给Animal 类型的对象引用变量a,然后当我调用方法时Sound()a 上,我应该得到barking 的输出(这是Dog 类中的重写方法),而是调用Animal's Sound() 方法,将输出作为I don't make any sound

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

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

【问题讨论】:

    标签: c# java inheritance implicit-conversion explicit-conversion


    【解决方案1】:

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

    【讨论】:

    • 是的,我收到了警告,你是对的......正如我所说我是 C# 新手,我不知道这种特殊情况,所以我忽略了警告......但是感谢您以简短而甜蜜的方式回答我的问题......
    【解决方案2】:

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

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

    【讨论】:

    • +1 让我知道这些方法在 Java 中默认是虚拟的,但在 C# 中却不是。
    【解决方案3】:

    考虑代码

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-04
      • 2011-03-13
      相关资源
      最近更新 更多