Reputation: 1478
Let there be class NaturalFood and two classes inherit from this class; class Fruits and class Vegetables
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
}
}
I want to enforce that any class derived from class NaturalFood must declare and/or override the AllList enumeration. Effectively the enumeration will contain list specific to the derived class. How do I do this ?
Edit: My basic requirement is that each class deriving from a base class must have its own list of "something" that is specific to it. Enumeration is just a way of creating a list. I hope you get the gist from my example. I want to take advantage of what Enumeration offers viz. intellisense, toString() etc.
Edit2: Isn't my example very practical enough ? If I put the entire enumeration in the base class (NaturalFood), how do I know which of the enumerated values are specific to which derived class ? Let us say each derived class is "publishing something" it has to offer in form of enumerated constants and I want to enforce this constraint on every derived class. So in other words, my question is how to enforce a constraint on derived class like in scenario described here ?
Upvotes: 4
Views: 2863
Reputation: 37660
Actually, there's no sense to override
these values. Actually, the advantages of override is that you can call a method of a derived class without knowing the derived class itself.
For example :
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");
}
}
No imagine what you wanted to do. In the main method, try to call the 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
}
This won't compile. The compiler has no way to know the actual derived class to infer the available enumeration values.
However, if you remove the enumeration from the base type, this will works :
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
}
But as you can see, you have to know explicitly the actual type, and thus, make the polymorphic useless.
[Edit] It's hard to answer to your second edit. Actually there are many many ways to validate such constraint. Without more context it may be difficult to answer. The most simple way I think, is to add to each derived class a overriden property that describe what kind of enumeration is accepted.
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;
}
}
}
But honestly, it start to add a lot of plumbing code, that become quite unreadable. You should consider the problem at a higher scope to find an acceptable solution.
Upvotes: 3
Reputation: 23685
This is not possible because enums are types, not class members... and the fact they are declared inside a class doesn't make them members of that class, they are just nested. Every class can and has to define it's own private enum AllList
type... so your actual code is the only possible way to go.
If you want to obtain something like this and you have only few values to deal with, stick with properties overrides:
class A
{
public virtual String Value
{
get
{
return "A";
}
}
}
class B : A
{
public override String Value
{
get
{
return "B";
}
}
}
Upvotes: 3