簡體   English   中英

如何強制派生類重寫基類的枚舉?

[英]How to enforce derived class to override an enumeration from the base class?

設自然食品類,從該類繼承兩個類; 水果和蔬菜類

 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枚舉。 實際上,枚舉將包含特定於派生類的列表。 我該怎么做呢 ?

編輯 :我的基本要求是,每個派生自基類的類都必須具有其特定的“內容”列表。 枚舉只是創建列表的一種方式。 我希望你能從我的榜樣中得到啟發。 我想利用枚舉提供的優勢。 intellisense,toString()等

Edit2:我的例子不夠實用嗎? 如果將整個枚舉放在基類(NaturalFood)中,我如何知道哪個枚舉值特定於哪個派生類? 讓我們說每個派生類都必須以枚舉常量的形式“發布某些東西”,我想在每個派生類上強制執行此約束。 因此,換句話說,我的問題是如何像在此描述的方案中那樣對派生類實施約束?

這是不可能的,因為枚舉是類型,而不是類成員……並且它們在類中聲明的事實並不會使它們成為該類的成員,而是將它們嵌套。 每個類都可以並且必須定義自己的private enum AllList類型...因此,實際的代碼是唯一可行的方法。 如果您想要獲得類似這樣的值,並且只需要處理很少的值,請堅持使用屬性覆蓋:

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

class B : A
{
    public override String Value
    {
        get
        {
            return "B";
        }
    }
}

實際上,沒有意義要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


}

但是正如您所看到的,您必須明確地知道實際的類型,從而使多態不再有用。

[編輯]很難回答您的第二次編輯。 實際上,有很多方法可以驗證這種約束。 沒有更多背景信息,可能很難回答。 我認為,最簡單的方法是向每個派生類添加一個重寫的屬性,該屬性描述了接受哪種枚舉。

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

但老實說,它開始添加很多管道代碼,這些代碼變得非常難以理解。 您應該在更大范圍內考慮該問題,以找到可接受的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM