15

Let's say Java has these hierarchical classes:

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();
        // a.m(); // doesn't work
        B b = new D();
        b.m();
        C c = new D();
        c.m();
        D d = new D();
        d.m();
    }
}

This is the (blind) duplication of the same code in 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();
        // a.M(); // doesn't work       
        B b = new D();
        b.M();
        C c = new D();
        c.M();
        D d = new D();
        d.M();
    }
}

When I execute the Java code, I got C-C-C whereas C# returns B-C-C.

To me C#'s result makes more sense, as reference B invokes its own method.

  • What's the logic behind the Java designer's decision to print C-C-C instead of B-C-C? I mean, why reference B uses the overriding method in C? What's the advantage of this approach?
  • How can I change Java code to print out B-C-C just like C# does? I mean, how can I teach java to invoke the method of the exact reference it uses?
  • How can I change C# code to print out C-C-C? I mean, how can I teach C# to invoke the overriding method?
Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
prosseek
  • 182,215
  • 215
  • 566
  • 871
  • 2
    It's a simple design issue - java uses dynamic dispatch by default, while C# doesn't, to get dynamic dispatch in C# you need to declare a method virtual and indicate that the overriding method is indeed overriding it. – amit Nov 10 '12 at 14:59
  • 1
    The D and A classes have no function here. You can omit them for a shorter (clearer) sample. – H H Nov 10 '12 at 14:59

4 Answers4

13

It's for the virtual function definition:

a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature. This concept is a very important part of the polymorphism portion of object-oriented programming (OOP).

In C#,you should declare the method as virtual in order to be overriden, as shown in MSDN:

Since the M method is not virtual, it will execute b.M() even if b variable is actually a D instance.

In Java, every non-static method is virtual by default, so you when you override a method (even without the @Override annotation) the behavior of the b.M() will be the d.M() that inherits the c.M() method behavior.

How can I change Java code to print out B-C-C just like C# does? I mean, how can I teach java to invoke the method of the exact reference it uses?

You simply can't do this in Java. The M method in C class would override the M method in B. Adding the final modifier to B#M will just make that C or other B children can't override the M() method.

How can I change C# code to print out C-C-C? I mean, how can I teach C# to invoke the overriding method?

Change the M method in B class to virtual and override it in C class:

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");
    }
}
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
9
  1. In java all of methods are virtual by default. And methods in derived classes override methods from base. In C# they are not.

  2. Seems like you can't do this. But you can prevent derived classes to override this method by declaring it as final.

  3. Declare this method with virtual keyword in base class and with override in derived.

tukaef
  • 9,074
  • 4
  • 29
  • 45
1

What's the logic behind the Java designer's decision to print C-C-C instead of B-C-C?

Java makes methods virtual by default. In the past there was an understanding that this was good practice, and at the time of Java's birth was perhaps at the peak of that understanding.

These days – while many do hold to it – there is also more resistance to it (particularly as virtual methods open up the class to unexpected sub-class implementation choices).

(NB. there is no right or wrong here, each approach has its advantages and disadvantages.)

How can I change Java code to print out B-C-C just like C# does?

Declare them final.

How can I change C# code to print out C-C-C?

Declare them virtual or abstract in the class that defines them (B in the question), and override in child classes.

Richard
  • 106,783
  • 21
  • 203
  • 265
0

What's the logic behind the Java designer's decision to print C-C-C instead of B-C-C? I mean, why reference B uses the overriding method in C? What's the advantage of this approach?

Look that you call method from D class object which inherited the M method from C class. The reference type doesn't matter in Java - the important part is which class has referenced object.

maba
  • 47,113
  • 10
  • 108
  • 118
Adam Sznajder
  • 9,108
  • 4
  • 39
  • 60