2012-11-10 295 views
11

比方說,Java有這些分級類:Java繼承與C#繼承

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(); 
    } 
} 

這是相同的代碼在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(); 
    } 
} 

當我執行Java代碼,我得到了C-C-C而C#返回B-C-C

對我來說C#的結果更有意義,因爲參考B調用它自己的方法。

  • Java設計師決定打印C-C-C而不是B-C-C的邏輯是什麼?我的意思是,爲什麼參考B在C中使用重載方法?這種方法的優點是什麼?
  • 如何才能像C#那樣更改Java代碼來打印出B-C-C?我的意思是,我如何教java來調用它使用的確切引用的方法?
  • 如何更改C#代碼以打印出C-C-C?我的意思是,我如何教C#調用重寫方法?
+2

這是一個簡單的設計問題 - java的默認使用動態分配,而C#不,讓動態在C#中調度你需要聲明一個虛擬的方法,並指出覆蓋的方法確實覆蓋了它。 – amit

+1

D和A類在這裏沒有功能。您可以省略它們以獲得更短(更清晰)的樣本。 –

回答

10

這對virtual function定義:

虛擬功能或者虛擬方法是一個函數或方法,其行爲可被繼承類內由函數具有相同簽名的覆蓋。這個概念是面向對象編程(OOP)多態部分的一個非常重要的部分。

在C#中,你應該以聲明方式爲虛擬被重寫,如在MSDN:

由於M方法不是虛擬的,它將執行b.M()即使b變量實際上是一個D實例。

在Java中,每一個方法是通過默認虛擬,讓您在重寫的方法(即使沒有@Override註釋)的b.M()的行爲將是繼承c.M()法行爲d.M()

如何更改Java代碼以便像C#一樣打印出B-C-C?我的意思是,我如何教java來調用它使用的確切引用的方法?

你根本無法在Java中做到這一點。 C類中的M方法將覆蓋B中的M方法。將final修飾符添加到B#M只會使C或其他B兒童無法覆蓋M()方法。

如何更改C#代碼以打印出C-C-C?我的意思是,我如何教C#調用重寫方法?

更改M方法Bvirtual並重寫它C類:

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"); 
    } 
} 
6
  1. Java中的所有方法都默認虛擬。派生類中的方法覆蓋來自base的方法。在C#中他們不是。

  2. 似乎你不能這樣做。但是,您可以通過聲明它爲final來防止派生類重寫此方法。

  3. 聲明此方法virtual基類中的關鍵字和override派生。

+0

+1的答案,但它會很好,如果你改說你的第三點與它指定的C# – exexzian

+3

你根本不能聲明B.m()作爲final,因爲它會阻止C.m()來覆蓋它。 – prosseek

+0

@prosseek真的。我的錯。編輯。 – 2kay

0

什麼是Java的設計者決定打印C-C-C代替B-C-C的背後的邏輯?我的意思是,爲什麼參考B在C中使用重載方法?這種方法的優點是什麼?

看你從C類中繼承了M方法的D類對象調用方法。引用類型在Java中無關緊要 - 重要的部分是哪個類引用了對象。

1

Java設計師決定打印C-C-C而不是B-C-C的邏輯是什麼?

Java使得方法默認爲虛擬。過去有一種理解,認爲這是一種很好的做法,而且在Java誕生的時候也許正處於這種理解的頂峯。現在 - 雖然很多人堅持這樣做 - 但也有更多的阻力(尤其是虛擬方法讓班級意識到子類實施的選擇出乎意料)。

(NB。沒有對錯,每一種方法都有其優點和缺點。)

我怎樣才能改變Java代碼打印出B-C-C一樣,C#不?

聲明它們final

如何更改C#代碼以打印出C-C-C?

聲明他們在定義它們的類(B的問題)virtualabstract,並override子類中。

+0

您需要使用'override'標記'C'的方法。 – CodesInChaos

+0

@CodesInChaos確實,也錯過了那個抽象意味着虛擬。 – Richard