繁体   English   中英

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

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

好! 我有相同的代码用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();
    }
}

输出: A类 它在C#中。

但是当在Java中运行相同的代码时,输​​出是B类 这是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();
 }
}

那么,为什么会出现不同的结果呢? 我知道,在Java中,默认情况下所有方法都是虚拟的,这就是Java输出B类的原因。

另一件事是,两种语言都声称它们是由C ++出现或启发的,然后为什么它们显示不同的结果,而两者都有相同的基本语言(Say)。

这条线A a = new B(); 实际上呢? 不是B持有对象吗? 如果是这样,那么为什么C#显示A类而Java显示B类

注意在采访中询问了上述相同代码的问题。 我回答了输出类B (关于Java),但他说A类将是正确的输出。

谢谢!

在Java中, 非静态方法是虚拟的 ,而在C#中,它们不是虚拟的 您需要在print方法中使用virtualoverride关键字才能在c#中获得相同的行为。

C#中的多态行为:

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

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

编辑

回到原始的C#代码,当您在子类及其超类中使用相同的方法签名时,您将在B.print上获得编译时警告,即:

'print'需要关键字'new',因为它隐藏了方法'MyNamespace.A.print()'

这是一个很好的迹象,表明该方法不会被多态/虚拟调用。 要避免警告(并保留原始的C#行为),在B中您需要添加new

    public new void print()

这是因为在派生类的C#方法中隐藏,而不是覆盖其基类的方法。 您想要覆盖的方法需要在基础中使用关键字virtual显式标记,并在派生类中使用关键字override

相反,在Java中,默认情况下所有方法都是虚拟的:只需指定相同的签名就足以覆盖。

以下是如何使您的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");
    }
}

A a = new B() ,变量a保持B对象,但输出是“A类”! 它不应该叫B类方法吗?

当您隐藏方法而不是覆盖它时,派生类会保留两个方法 - 基类中的方法和派生类中的方法。 外部呼叫者仍可以访问这两种方法。 他们可以通过使用适当静态类型的对象来决定调用哪两个方法。 这是一个例子:

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

在ideone上演示。

使用virtual / override ,只能从外部访问一个方法 - 即派生类中的方法。 基类中的方法可以通过派生类的方法访问,但不能由派生类的外部用户访问。

暂无
暂无

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

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