4

クラス NaturalFood があり、このクラスから継承する 2 つのクラスがあるとします。クラスの果物とクラスの野菜

 abstract class NaturalFood
{
    enum AllList
    {
        //empty list as a placeholder
    }

   protected string Name;
}

class Fruits : NaturalFood 
{
    enum AllList
    {
        Apple = 1,
        Banana = 2
    }
}

class Vegetables : NaturalFood
{
    enum AllList
    {
        Carrot = 1,
        Potatoes = 2
    }

}

クラス NaturalFood から派生したすべてのクラスは、AllList 列挙を宣言および/またはオーバーライドする必要があることを強制したいと考えています。事実上、列挙には派生クラスに固有のリストが含まれます。これを行うにはどうすればよいですか?

編集:私の基本的な要件は、基本クラスから派生した各クラスには、それに固有の「何か」の独自のリストが必要です。列挙は、リストを作成する単なる方法です。私の例から要点を理解していただければ幸いです。Enumeration が提供するものを利用したいです。インテリセンス、toString() など。

Edit2:私の例は非常に実用的ではありませんか? 列挙全体を基本クラス (NaturalFood) に配置した場合、どの列挙値がどの派生クラスに固有のものかをどのように知ることができますか? 各派生クラスは、列挙された定数の形式で提供する必要がある「何かを公開」しており、すべての派生クラスにこの制約を適用したいとしましょう。つまり、私の質問は、ここで説明されているシナリオのように、派生クラスに制約を適用する方法ですか?

4

2 に答える 2

3

実際、overrideこれらの値には意味がありません。実際、オーバーライドの利点は、派生クラス自体を知らなくても、派生クラスのメソッドを呼び出すことができることです。

例えば ​​:

static void Main()
{
    NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
    food.SomeMethodInBaseClass(); // ok

}

static NaturalFood GetSomeFood()
{
     if(somecondition) {
         return new Fruits();
     } 
     else{
         return new Vegetables();
     }
}

public abstract class NaturalFood
{
     public abstract void SomeMethodInBaseClass();
}

public class Fruits : NaturalFood 
{       
   public override void SomeMethodInBaseClass(){
        Console.WriteLine("I'm a fruit");
    }
}

public class Vegetables : NaturalFood
{    
    public override void SomeMethodInBaseClass(){
         Console.WriteLine("I'm a vegetable");
    }   
}

あなたが何をしたか想像できません。mainメソッドで、AllListを呼び出してみてください。

static void Main()
{
    NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
    food.SomeMethodInBaseClass(); // ok
    food.AllList.XXXX; // What? it won't compile
}

これはコンパイルされません。コンパイラーには、使用可能な列挙値を推測するための実際の派生クラスを知る方法がありません。

ただし、基本タイプから列挙を削除すると、これは機能します。

static void Main()
{
    NaturalFood food = GetSomeFood(); // At this point, we don't know the actual type
    food.SomeMethodInBaseClass(); // ok

    Fruits f = new Fruits();
    Console.WriteLine(    f.AllList.Apple); // Ok

    Vegetable v = new Vegetable ();
    Console.WriteLine(    v.AllList.Potatoe); // Ok


}

しかし、ご覧のとおり、実際の型を明示的に知る必要があるため、多型を役に立たなくします。

[編集] 2回目の編集に答えるのは難しいです。実際、そのような制約を検証する方法はたくさんあります。これ以上の文脈がなければ、答えるのは難しいかもしれません。私が考える最も簡単な方法は、どの種類の列挙が受け入れられるかを説明するオーバーライドされたプロパティを各派生クラスに追加することです。

public enum NaturalFoodType {
    Unknown = 0,
    Apple= 1,
    Banana = 2,
    Potatoe = 3,
    Cucumber = 4
}
public abstract class NaturalFood
{
     public abstract void SomeMethodInBaseClass();
     public abstract IEnumerable<NaturalFoodType> AcceptedFoodType { get; }

     public bool IsValid(NaturalFoodType type){
          return AcceptedFootType.Contains(type);
     }
}

public class Fruits : NaturalFood 
{       
    public override void SomeMethodInBaseClass(){
        Console.WriteLine("I'm a fruit");
    }
    public override NaturalFoodType {
        get {
             yield return NaturalFoodType.Apple;
             yield return NaturalFoodType.Banana;
        }
    }
}

public class Vegetables : NaturalFood
{    
    public override void SomeMethodInBaseClass(){
         Console.WriteLine("I'm a vegetable");
    } 
    public override NaturalFoodType {
        get {
             yield return NaturalFoodType.Potatoe;
             yield return NaturalFoodType.Cucumber;
        }
    }  
}

しかし、正直なところ、それは多くの配管コードを追加し始め、それはかなり読めなくなります。許容できる解決策を見つけるには、より高い範囲で問題を検討する必要があります。

于 2013-01-18T13:02:26.933 に答える
3

列挙型はクラスメンバーではなく型であるため、これは不可能です...そして、それらがクラス内で宣言されているという事実は、それらをそのクラスのメンバーにせず、ネストされているだけです。すべてのクラスは独自の型を定義でき、定義する必要がありprivate enum AllListます...したがって、実際のコードが唯一の可能な方法です。このようなものを取得したいが、処理する値がほとんどない場合は、プロパティのオーバーライドを使用してください。

class A
{
    public virtual String Value
    {
        get
        {
            return "A";
        }
    }
}

class B : A
{
    public override String Value
    {
        get
        {
            return "B";
        }
    }
}
于 2013-01-18T11:11:37.073 に答える