簡體   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