创建一个类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";
}
}
}