如何强制派生类覆盖基类中的枚举

本文关键字:枚举 基类 覆盖 何强制 派生 | 更新日期: 2023-09-27 17:54:04

创建一个类NaturalFood,并从这个类继承两个类;类水果类蔬菜

 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枚举。实际上,枚举将包含特定于派生类的列表。我该怎么做呢?

Edit:我的基本要求是每个从基类派生的类必须有自己的特定于它的"某些东西"列表。枚举只是创建列表的一种方式。我希望你能从我的例子中得到要点。我想利用枚举提供的优势,即智能感知,toString()等。

Edit2:我的例子不是很实用吗?如果我将整个枚举放在基类(NaturalFood)中,我如何知道哪些枚举值特定于哪个派生类?假设每个派生类都以枚举常量的形式"发布某些东西",我想对每个派生类强制执行此约束。所以换句话说,我的问题是如何像这里描述的场景那样对派生类强制约束?

如何强制派生类覆盖基类中的枚举

实际上,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

}

但是正如您所看到的,您必须明确地知道实际类型,因此,使多态无用。

[Edit]很难回答你的第二次编辑。实际上,有很多方法可以验证这种约束。如果没有更多的背景,可能很难回答。我认为最简单的方法是为每个派生类添加一个重写属性,该属性描述接受哪种枚举。

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

但老实说,它开始添加大量的管道代码,变得相当不可读。您应该在更高的范围内考虑这个问题,以找到一个可接受的解决方案。

这是不可能的,因为枚举是类型,而不是类成员…它们在类中声明的事实并不能使它们成为该类的成员,它们只是嵌套的。每个类都可以并且必须定义自己的private enum AllList类型…所以你的实际代码是唯一可行的方法。如果您想获得类似这样的内容,并且您只有几个值需要处理,则坚持使用属性覆盖:

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