2012-01-13 52 views
21

我想告訴我ItemA和ItemB的名稱。它應該告訴我「Subitem \ nSubitem」,但它會告訴我「Item \ nSubitem」。這是因爲Subitem類中定義的「Name」變量在技術上與基類Item中定義的「Name」變量不同。我想將原始變量更改爲新值。我不明白爲什麼這不是最簡單的事情,考慮到虛擬和覆蓋完美的方法。我已經完全無法知道如何實際覆蓋一個變量。如何覆蓋,而不是隱藏,在C#子類中的成員變量(字段)?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Example 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      System.Console.WriteLine(ItemA.Name); 
      System.Console.WriteLine(ItemB.Name); 
      System.Console.ReadKey(); 
     } 
     static Item ItemA = new Subitem(); 
     static Subitem ItemB = new Subitem(); 
    } 
    public class Item 
    { 
     public string Name = "Item"; 
    } 
    public class Subitem : Item 
    { 
     new public string Name = "Subitem"; 
    } 
} 
+1

您需要的東西可以是* virtual * - a * Property *(「Getter」)或* Method *。成員變量*從不*虛擬。 – 2012-01-13 01:11:30

回答

29

你不能覆蓋變量在C#中,但是你可以重寫屬性:

public class Item 
{ 
    public virtual string Name {get; protected set;} 
} 
public class Subitem : Item 
{ 
    public override string Name {get; protected set;} 
} 

另一種方法是改變子類中的值,就像這樣:

public class Item 
{ 
    public string Name = "Item"; 
} 
public class Subitem : Item 
{ 
    public Subitem() 
    { 
     Name = "Subitem"; 
    } 
} 
+1

@ Eagle-Eye多態變量會做什麼?如果你無法表達理論,不要批評這種做法。 – 2012-01-13 02:17:25

+0

+1 Jon,@ Eagle-Eye。鑑於多態性是用派生類型中的*功能*代替的,將它應用於類似字段(沒有功能)的東西是沒有意義的。 – 2012-01-13 03:50:16

+0

@Jon現在重新評論我的評論,這有點愚蠢。我真正的意思是,我希望我可以在一個子類中設置一個變量的默認值,而不必在構造函數中設置它(因爲我來自於腳本語言,它是如何完成的)。我以前表現得很差。但是,如果你無法表達理論,「不批評實踐」甚至意味着什麼?至於「其他方法看起來很愚蠢和拙劣」,我指的是我只是爲了獲得一個單獨的默認值而創建一個get方法。 (然而,我很後悔使用愚蠢這個詞。) – 2012-12-28 09:56:01

8

有多態性與領域(你叫什麼一個變量)沒有概念(這是什麼使override做它的東西)。你需要在這裏使用的是一個屬性。

public class Item 
{ 
    public virtual string Name 
    { 
     get { return "Item"; } 
    } 
} 

public class SubItem : Item 
{ 
    public override string Name 
    { 
     get { return "Subitem"; } 
    } 
} 
+1

雖然他可能不會硬編碼這樣的值,但它可能會有所不同。 – 2012-01-13 01:11:49

+0

絕對正確。 「虛擬變量」是沒有意義的。這是Java風格的「getter()」和「setter()」方法如此有用的原因的很大一部分。而C#的「屬性」(來自Delphi已經非常好的屬性的改進)的概念消除了對getter/setter方法的大量需求。 「屬性」絕對是這個問題的答案。另見這個線程:http://stackoverflow.com/questions/1112458/c-sharp-member-variable-overrides-used-by-base-class-method – paulsm4 2012-01-13 01:14:05

+1

@JeffMercado:雖然是真的,我試圖堅持如下到OP的問題的原始形式,以表明我在談論的區別(屬性與領域)。 – 2012-01-13 01:15:32

0

可能的解決方案是使用屬性並覆蓋其吸氣劑,如下所示:

public class Item 
{ 
    public virtual string Name { get { return "Item"; } } 
} 
public class Subitem : Item 
{ 
    public override string Name { get { return "Subitem"; } } 
} 
+1

這會阻止稍後改變數值。 – x3ro 2017-08-12 21:18:26

4

「覆蓋變量」是什麼意思?

變量是概念性內存中的命名位置(「概念性」,因爲它可能是一個寄存器,儘管不太可能帶有字段)。

覆蓋方法會將一組操作替換爲另一組操作。

由於內存中的指定位置不是一組操作,您如何替換它?那些期望在內存中使用該命名位置的東西應該做什麼?

如果你想改變存儲在內存中,然後就這樣做時,派生類的構造:

public class Item 
{ 
    public string Name = "Item"; 
} 
public class Subitem : Item 
{ 
    public SubItem() 
    { 
    Name = "Subitem"; 
    } 
} 

如果你想覆蓋的一組操作,然後定義一組操作(方法或屬性)來覆蓋。

1

這個問題比較陳舊,作者可能使用C#5.0或更低版本。但我有同樣的問題,並遇到了一個非常整潔的解決方案,與C#6.0及更高版本一起使用,我想與您分享:

C#6.0提供了初始化自動屬性的功能。所以我們可以使用:

public class Item 
{ 
    public virtual string Name { get; set; } = "Item"; 
} 

public class Subitem : Item 
{ 
    public override string Name { get; set; } = "Subitem"; 
}