11

Ok! I have same code written in Java and C# but the output is different!

class A
{
    public void print() 
    {
        Console.WriteLine("Class A");
    }
}

class B : A 
{
    public void print()
    {
        Console.WriteLine("Class B");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
        a.print();
        Console.Read();
    }
}

Output: Class A. It is in C#.

But when same code was ran in Java, the output was Class B. Here is the Java Code:

class A
{
    public void print() 
    {
        System.out.println("Class A");
    }
}

class B extends A 
{
    public void print()
    {
        System.out.println("Class B");
    }
}


public class Program{

 public static void main(String []args){
    A a = new B();
    a.print();
 }
}

So, why this is showing different results? I do know that, in Java, all methods are virtual by default that's why Java outputs Class B.

Another thing is that, both languages claim that they are emerged or inspired by C++ then why they are showing different results while both have same base language(Say).

And what does this line A a = new B(); actually doing? Isn't a holding object of class B? If it is so, then why C# displays Class A and Java shows Class B?

NOTE This question was asked in interview with the same code provided above. And I answered with output Class B (with respect to Java) but he said Class A will be right output.

Thank you!

Faizan Mubasher
  • 4,427
  • 11
  • 45
  • 81
  • A.print is called because C# is using variable type (not actual object type) to call non-virtual methods. For virtual methods, actual object type is used to find target method. – PashaPash Jan 22 '14 at 12:19
  • If both languages behaved the same in all circumstances, there wouldn't *be* two languages. – Damien_The_Unbeliever Jan 23 '14 at 07:16

2 Answers2

5

This is because in C# methods of derived classes hide, not override, methods of their base class. The methods that you would like to override need to be explicitly marked with the keyword virtual in the base, and with the keyword override in the derived classes.

In contrast, in Java all methods are virtual by default: simply specifying the same signature is sufficient for an override.

Here is how to make your C# program an equivalent of Java program:

class A
{
    public virtual void print() // Add "virtual"
    {
        Console.WriteLine("Class A");
    }
}

class B : A 
{
    public override void print()// Add "override"
    {
        Console.WriteLine("Class B");
    }
}

After A a = new B(), variable a is holding object of B but the output is "Class A"! Shouldn't it call method of class B?

When you hide a method, rather than overriding it, your derived class keeps both methods - the one in the base class, and the one in the derived class. Both these methods remain accessible to the outside callers. They can decide which of the two methods to call by using an object of an appropriate static type. Here is an example:

    B b = new B();
    b.print();      // Prints "Class B"
    ((A)b).print(); // Prints "Class A"

Demo on ideone.

When you use virtual/override, you can access only one method from the outside - namely, the one in the derived class. The method in the base class can be accessed by methods of the derived class, but not by the outside users of the derived class.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks! I know how to make equivalent! I posted question after testing! The line "A a = new B()" is confusing to me. "a" is holding object of "B" but the output is "Class A"! Shouldn't it call method of class "B"? Or it is a language construct? – Faizan Mubasher Jan 22 '14 at 12:10
4

In Java, non-static methods are virtual, whereas in C#, they are not. You will need to use the virtual and override keywords on your print method to get the same behaviour in c#.

Polymorphic behaviour in C#:

class A
{
    public virtual void print() 
    {
        Console.WriteLine("Class A");
    }
}

class B : A 
{
    public override void print()
    {
        Console.WriteLine("Class B");
    }
}

Edit

Getting back to your original C# code, you will get a compile time warning on B.print when you use the same method signature in both a subclass and its superclass, viz:

The keyword 'new' is required on 'print' because it hides method 'MyNamespace.A.print()'

This is a good indication that the method won't be called polymorphically / virtually. To avoid the warning (and retain your original C# behaviour), in B you would need to add new:

    public new void print()
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Right! I am a bit confuse here! A a = new B(); Now "a" is holding object of "B". Then why the method of Class "A" is called? – Faizan Mubasher Jan 22 '14 at 12:05
  • 1
    `A a = new B();` assigns the variable of superclass `a` to the subclass instance of `B`. However, without polymorphic behaviour, the compiler will early bind the call to `A.print`. (Whereas late binding would result in `B.print`) – StuartLC Jan 22 '14 at 12:17
  • O Yes! That's the point. It means that Java exhibits late binding behavior? – Faizan Mubasher Jan 22 '14 at 12:20
  • You can check Java code here: http://www.compileonline.com/compile_java_online.php – Faizan Mubasher Jan 22 '14 at 12:26