简体   繁体   English

Java Vs C#:带有方法覆盖的Java和C#子类在同一场景中输出不同的结果

[英]Java Vs C#: Java and C# subclasses with method overrides output different results in same scenario

Ok! 好! I have same code written in Java and C# but the output is different! 我有相同的代码用JavaC#编写,但输出不同!

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 . 输出: A类 It is in C#. 它在C#中。

But when same code was ran in Java , the output was Class B . 但是当在Java中运行相同的代码时,输​​出是B类 Here is the Java Code: 这是Java代码:

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 . 我知道,在Java中,默认情况下所有方法都是虚拟的,这就是Java输出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). 另一件事是,两种语言都声称它们是由C ++出现或启发的,然后为什么它们显示不同的结果,而两者都有相同的基本语言(Say)。

And what does this line A a = new B(); 这条线A a = new B(); actually doing? 实际上呢? Isn't a holding object of class B ? 不是B持有对象吗? If it is so, then why C# displays Class A and Java shows Class B ? 如果是这样,那么为什么C#显示A类而Java显示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. 我回答了输出类B (关于Java),但他说A类将是正确的输出。

Thank you! 谢谢!

In Java, non-static methods are virtual , whereas in C#, they are not. 在Java中, 非静态方法是虚拟的 ,而在C#中,它们不是虚拟的 You will need to use the virtual and override keywords on your print method to get the same behaviour in c#. 您需要在print方法中使用virtualoverride关键字才能在c#中获得相同的行为。

Polymorphic behaviour in C#: 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: 回到原始的C#代码,当您在子类及其超类中使用相同的方法签名时,您将在B.print上获得编译时警告,即:

The keyword 'new' is required on 'print' because it hides method 'MyNamespace.A.print()' 'print'需要关键字'new',因为它隐藏了方法'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 : 要避免警告(并保留原始的C#行为),在B中您需要添加new

    public new void print()

This is because in C# methods of derived classes hide, not override, methods of their base class. 这是因为在派生类的C#方法中隐藏,而不是覆盖其基类的方法。 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. 您想要覆盖的方法需要在基础中使用关键字virtual显式标记,并在派生类中使用关键字override

In contrast, in Java all methods are virtual by default: simply specifying the same signature is sufficient for an override. 相反,在Java中,默认情况下所有方法都是虚拟的:只需指定相同的签名就足以覆盖。

Here is how to make your C# program an equivalent of Java program: 以下是如何使您的C#程序等效于Java程序:

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"! A a = new B() ,变量a保持B对象,但输出是“A类”! Shouldn't it call method of class B ? 它不应该叫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. 在ideone上演示。

When you use virtual / override , you can access only one method from the outside - namely, the one in the derived class. 使用virtual / override ,只能从外部访问一个方法 - 即派生类中的方法。 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. 基类中的方法可以通过派生类的方法访问,但不能由派生类的外部用户访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM