2012-01-13 12 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 *のようなものが必要です。メンバー変数は* never * virtualです。 –

答えて

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多型変数は何をしますか?あなたが理論を明確にすることができないならば、練習を批判しないでください。 –

+0

+1 to Jon、@ Eagle-Eye。多形性は派生型の*機能*を置き換えることを前提としているため、フィールド(機能を持たない)に何かを適用することは意味がありません。 –

+0

@Jon今、私のコメントを書き直してみると、それはちょっと愚かなことでした。私が本当に意味していたのは、コンストラクタ内に変数を持たずに子クラス内の変数のデフォルト値を設定できることでした。私はそれ以前にそれを表現するのに苦労しました。しかし、「理論を明確にすることができなければ、練習を批判しない」とはどういう意味ですか? 「他の方法は愚かでハッキリに見える」限り、私は単純に別のデフォルト値を持つメソッドを作ることを指していました。 (しかし、私は愚かな言葉の使用を後悔します。) –

8

フィールド(あなたが変数と呼んでいるもの)と(overrideはそのことを行う作るものです)多型の概念はありません。代わりにここで使用する必要があるのはプロパティです。

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

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

彼はおそらくそのような値をハードコードしないでしょうが、それは変わるかもしれません。 –

+0

絶対に正しい。 「仮想変数」は意味をなさない。なぜJavaスタイルの "getter()"や "setter()"メソッドがとても有用なのかは、大きな部分を占めています。そしてC#の "プロパティ"(Delphiの非常に優れた "プロパティ"からの前進)の概念は、ゲッター/セッターメソッドの必要性をほとんど排除します。 "プロパティ"は間違いなくこの質問に対する答えです。このスレッドも参照してください:http://stackoverflow.com/questions/1112458/c-sharp-member-variable-overrides-used-by-base-class-method – paulsm4

+1

@JeffMercado:真実の間、私は密接にOPの質問の元の形に変換して、私が話している区別を実証する(プロパティ対フィールド)。 –

0

可能な解決策はそうのように、プロパティを使用し、そのゲッターを上書きすることです:

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

これは、後で値を変更できなくなります。 – x3ro

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"; 
} 
関連する問題