Javainheritance与C#inheritance

假设Java有这些分层类:

class A { } class B extends A { public void m() { System.out.println("B\n"); } } class C extends B { public void m() { System.out.println("C\n"); } } class D extends C { public static void main(String[] args) { A a = new D(); // am(); // doesn't work B b = new D(); bm(); C c = new D(); cm(); D d = new D(); dm(); } } 

这是C#中相同代码的(盲目)复制:

 using System; class A { } class B : A { public void M() { Console.WriteLine("B"); } } class C : B { public void M() // I need to use public new void M() to avoid the warning { Console.WriteLine("C"); } } class D : C { public static void Main(String[] args) { A a = new D(); // aM(); // doesn't work B b = new D(); bM(); C c = new D(); cM(); D d = new D(); dM(); } } 

当我执行Java代码时,我获得了CCC而C#返回了BCC

对我来说,C#的结果更有意义,因为引用B调用它自己的方法。

  • Java设计师决定打印CCC而不是BCC的逻辑是什么? 我的意思是,为什么参考B使用C中的重写方法? 这种方法有什么优势?
  • 如何像C#一样更改Java代码以打印出BCC ? 我的意思是,我如何教java调用它使用的确切参考方法?
  • 如何更改C#代码以打印出CCC ? 我的意思是,我如何教C#调用重写方法?

这是为虚函数定义:

虚函数或虚方法是一种函数或方法,其行为可以通过具有相同签名的函数在inheritance类中重写。 这个概念是面向对象编程(OOP)的多态部分的一个非常重要的部分。

在C#中,您应该将方法声明为虚拟,以便被覆盖,如MSDN中所示:

  • 10.5.3虚拟方法 (来自VS 2003,但它是最新的)
  • C#虚拟

由于M方法不是虚方法,即使b变量实际上是D实例,它也会执行bM()

在Java中,默认情况下每个方法都是虚拟的,因此当您覆盖方法时(即使没有@Override注释), bM()的行为将是inheritancecM()方法行为的dM()

如何像C#一样更改Java代码以打印出BCC? 我的意思是,我如何教java调用它使用的确切参考方法?

你根本无法用Java做到这一点。 C类中的M方法将覆盖BM方法。 将final修饰符添加到B#M只会使C或其他B子项无法覆盖M()方法。

如何更改C#代码以打印出CCC? 我的意思是,我如何教C#调用重写方法?

B类中的M方法更改为virtual并在C类中覆盖它:

 class B : A { public virtual void M() { Console.WriteLine("B"); } } class C : B { public override void M() // I need to use public new void M() to avoid the warning { Console.WriteLine("C"); } } 
  1. 在java中,默认情况下所有方法都是虚拟的。 派生类中的方法会覆盖base的方法。 在C#中他们不是。

  2. 好像你不能这样做。 但是您可以通过将派生类声明为final来阻止派生类重写此方法。

  3. 在基类中使用virtual关键字声明此方法,并在派生中使用override

Java设计师决定打印CCC而不是BCC的逻辑是什么?

Java默认使方法成为虚拟方法。 在过去,有一种理解认为这是一种很好的做法,而在Java诞生的时候,也许正处于这种理解的顶峰。

这些天 – 虽然很多人坚持这一点 – 但它也有更多的阻力(特别是当虚拟方法打开了类到意外的子类实现选择时)。

(注意:这里没有对错,每种方法都有其优点和缺点。)

如何像C#一样更改Java代码以打印出BCC?

宣布他们是final

如何更改C#代码以打印出CCC?

在定义它们的类中声明它们是virtualabstract的(问题中的B ),并在子类中override

Java设计师决定打印CCC而不是BCC的逻辑是什么? 我的意思是,为什么参考B使用C中的重写方法? 这种方法有什么优势?

看你从D类对象中调用方法,该对象从C类inheritance了M方法。 引用类型在Java中无关紧要 – 重要的部分是哪个类引用了对象。