2016-07-30 14 views
-1

として私はたとえば...派生オブジェクトをインスタンス化するためのプレースホルダとして使用されている抽象基底クラスのオブジェクトを持っている状況を持っている...C#インスタンス化ベースオブジェクト派生オブジェクト

public abstract class Fruit(){ //stuff} 

public class Banana() : Fruit(){ //stuff } 

public class Apple() : Fruit(){ //stuff } 

public class FruitSalad() 
{ 
Fruit SomeKindOfFruit; 
public DoStuff(Fruit frt) 
{ 
    SomeKindOfFruit = new ????? 
} 
} 

だから機能は果物を受け入れるつもりです...プログラムは果物の種類を知らない...アップルになる可能性があります...バナナになる可能性があります...キウイかもしれません...しかし、私はそれが必要です入力frtを取って、SomeKindOfFruitに "こんにちは.. frtはアップルだから、あなたは今アップルになっている"と言います。

私はSomeKindOfFruit = new Apple()を知っています。私がしなければならないことは、if/thenステートメントの束をハードコーディングするか、型を評価して可能なすべての派生クラスを明示的に宣言しなければならないことです。クラス...派生クラスの派生クラス...広告のnauseum ...特にそれを行うには、とにかくそれを評価するためにとにかく型を引っ張らなければならないので、それは非常に簡単に言うことができるだろう、 "この派生物を見ますか?このことが何であれ、あなたは今、そのタイプのものです"。ただ1つのコードで、必要な数の派生クラスを作成することができます。私は、評価を追加するために繰り返し行う必要はありません。

私が考えたものである...と私は当初、単純な操作を行うことを試みた...式に等しく、それがnull参照の例外がスローされます[EDIT]

。さて、私が実際にやっていることは果物とは関係ありませんが、それは雑草に迷わずに問題を説明する最も簡単な方法でした。実際のプログラムがやっていることは、私は2つのクラスを持っています...よく、GUIコンポーネントを実行する1つのクラスと、フードの下で操作されるすべてのデータ型であるクラスのセット(ベース+派生クラス)ネットワーク。それらのクラスのそれぞれの中で私は、理論上はお互いを参照することになっているオブジェクトを作成しました。シーケンスは、格納されたSQLデータからデータクラスが作成されることです。すべてのデータが作成されたら、GUI上に表示するグラフィッククラスを作成するメソッドがデータクラスにあります。その部分は、データクラスは、グラフィックスクラスに自身へのリフレクションを与えることになっているので、両方のクラスが他のクラスへの参照を持ち、両方向に情報が移動できるようになっています...グラフィックスコンポーネントを介して関連するデータクラスとデータクラスは、ネットから情報を取得し、それをグラフィカルに表示することができます。

public abstract class baseData() { 
public graphicClass GraphicRepresentation; 

    public baseData(stuff){ 
    //Sets all the relevant data 
    } 

    public void Activate(){ 
    GraphicRepresentation = new graphicClass(); 
    //Sets all the relevant components in the class 
    GraphicRepresentation.DataReference = this; 
    }` 
    } 

上記はnull参照例外をスローします。私が考えることができるのは、baseDataオブジェクトであるDataReferenceを "これ"を割り当てる前にインスタンス化する必要がありますが、抽象クラスをインスタンス化できないため、インスタンス化できる必要がありますどんな派生型であっても、 "this"は "this"と同等にすることができます。

+0

'SomeKindOfFruit = frt' ????それがうまくいかない理由はあまり明確ではありません。 –

+0

問題が見つかった場合は、質問を破棄しないでください。コメントにあなたの発見を説明して、あなたの質問にオフトピック - >タイプミスとしてフラグを立てるだけです。元の質問に戻りました。 – honk

+0

[この改訂版](http://stackoverflow.com/revisions/38669603/3)に掲載されたOPの説明のため、タイプミスとしてクローズしています。 – honk

答えて

2

あなたはあなたの方法は、一般的な作ることができます:

public class FruitSalad() 
{ 
    Fruit SomeKindOfFruit; 

    public DoStuff<TFruit>(TFruit frt) 
     where TFruit : Fruit, new() 
    { 
     SomeeKindOfFruit = new TFruit(); 
    } 
1

私はあなたがポイントを逃していると思います。

まず、DoStuffの方法はtemporary field code smellを示唆しています。クラスフィールドは、メソッドではなくコンストラクタで初期化されることを意味します。私はFruitSaladクラスを実装した場合、私はおそらくそれが好きで記述します。

public class FruitSalad 
{ 
    private readonly Fruit _fruit; 

    public FruitSalad(Fruit fruit) 
    { 
     _fruit = fruit; 
    } 

    public DoStuff() 
    { 
     // Act on the _fruit field 
    } 
} 

第二に、Fruitの実際の実行時の型が限りFruitSaladのコンストラクタ/ DoStuffメソッドに渡されているかは重要ではありませんFruitから派生したものです。これはpolymorphismです。同様にFruitabstract方法CutToPiecesあった場合

は、例えば、:AppleBanana

public abstract class Fruit 
{ 
    public abstract void CutToPieces(); 
} 

は次のように実装されている:

public class Apple : Fruit 
{ 
    public override void CutToPieces() 
    { 
     Console.WriteLine("Apple being diced"); 
    } 
} 

public class Banana : Fruit 
{ 
    public override void CutToPieces() 
    { 
     Console.WriteLine("Banana being cut to small pieces"); 
    } 
} 

あなたFruitSaladまだ実際に知ることなく調製することができます。実行中のFruitインスタンスのインスタンスは、

public class FruitSalad 
{ 
    private readonly Fruit _fruit; 

    public FruitSalad(Fruit fruit) 
    { 
     _fruit = fruit; 
    } 

    public DoStuff() 
    { 
     // Prints "Apple being diced" or "Banana being cut to small pieces" 
     // depending on the runtime type of `Fruit` being passed into the 
     // constructor of FruitSalad 
     _fruit.CutToPieces(); 
    } 
} 
+0

私はさらに情報を追加しました。 –

0

CLRは、すでにこのための施設があります。

interface IFruit 
{ 
    void CutFruit(); 
} 


class Apple : IFruit 
{ 
    public void IFruit.CutFruit() 
    { 
     // Implementation for apple 
     // For fruits that do not support cutting, you still need to 
     // implement the interface, but you can throw a NotSupportedException 
     // and then catch the exception in the FruitSalad class 
    } 
} 

class Grape : IFruit 
{ 
    public void IFruit.CutFruit() 
    { 
     throw new NotSupportedException("You don't cut grapes..."); 
    } 
} 

class FruitSalad 
{ 
    IFruit[] _fruits = null; // Initialize in constructor or through property 

    void CutFruits() 
    { 
     foreach (IFruit fruit in _fruits) 
     { 
      try 
      { 
       fruit.CutFruit(); 
      } 
      catch (NotSupportedException ex) 
      { 
       Debug.Print(ex.Message); 
      } 
     } 
    } 
} 
:あなたは、あなたの代わりに相続の構成を使用する必要があります推測し、すべての種類を介してスイッチングの取り扱いを回避したい場合は

void GetFruitType(Fruit fruit) 
{ 
    Type t = fruit.GetType(); 
    if (t.Equals(typeof(Apple))) HandleApple(); 
} 

Compositionはここでの選択肢のように思えますが、継承チェーンを短くし、派生クラスに果実特有の実装を保持します。単一の責任の原則とそのすべて。

関連する問題