4

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

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

Edit2:我的例子还不够实用吗?如果我将整个枚举放在基类 (NaturalFood) 中,我如何知道哪些枚举值特定于哪个派生类?让我们说每个派生类都在“发布一些东西”,它必须以枚举常量的形式提供,我想对每个派生类强制执行这个约束。所以换句话说,我的问题是如何像这里描述的场景那样对派生类实施约束?

4

2 回答 2

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 回答
3

实际上,override这些值没有任何意义。实际上,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;
        }
    }  
}

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

于 2013-01-18T13:02:26.933 回答