How can I have a kind of virtual static member in c#
I have a class like:
public class Food
{
public static IList<Ingredient> i开发者_开发百科ngredients
public bool uses(Ingredient i)
{
return ingredients.Contains(i);
}
}
Then I inherit from it to make various kinds of food like:
public class Cake : public Food
{
public static IList<Ingredient> ingredients = new List<Ingredient>()
{
Sugar,
Eggs,
Milk
}
}
Now I want to be able to do
Food f = getFood();
if (f.uses(Eggs))
{
// Do something
}
So I want to have a static list of ingredients that (for example) all cakes can share, rather than a list per instance of Cake and be able to access it in a virtual way.
I'm willing to stir the code around to get a similar effect if needed!
In such cases, the OOD "prefer" to make the class Food
abstract, since the "Ingredients" will be different from a Food
to another. Thus, as others have pointed out, making this list static
is meaningless, since static
should be a modifier to an attribute which is not differentiating by the objects.
I suggest a solution as follows:
public abstract class Food
{
public abstract IList<Ingredient> Ingredients
{
get;
}
}
Now any class - to be a concrete - will be driven from Food
and therefore it must implement this property so that it gives its own ingredients
:
public class Cake : Food
{
public override IList<Ingredient> Ingredients
{
get {
return new IList<Ingredient>()
{ Sugar, Eggs, Milk };
}
}
}
You could define a method GetIngredients()
that the subclasses override:
public abstract class Food
{
public static IList<Ingredient> ingredients
public bool uses(Ingredient i)
{
return GetIngredients().Contains(i);
}
protected abstract IList<Ingredient> GetIngredients();
}
public class Cake : public Food
{
public static IList<Ingredient> ingredients = new List<Ingredient>()
{
Sugar,
Eggs,
Milk
}
protected override IList<Ingredient> GetIngredients()
{
return ingredients ;
}
}
What about making all of this instances of one class? like:
class Food
{
public IList<Ingredient> ingredients;
public Food(IList<Ingredient> ingredients)
{
this.ingredients = ingredients.Clone();
}
public bool uses(Ingredient i)
{
return ingredients.Contains(i);
}
}
Food Cake = new Food({ Sugar, Eggs, Milk });
The ingredients do not need to be static. You can have all types of different cakes derive from the Cake class so that they inherit the common ingredients:
public class Cake : Food
{
public IList<Ingredient> ingredients = new List<Ingredient>()
{
Sugar,
Eggs,
Milk
}
}
public class DevilsFoodCake : Cake
{
public DevilsFoodCake()
{
ingredients.AddRange(new List<Ingredient>()
{
Chocolate,
SourCream
}
}
}
You can't really if you aim it to have one collection of ingredients per type. I think the best you could do, although not something I'd not necessarily recommend, is move the responsibly to another class like so:
public class IngredientStore
{
public static IngredientStore Current
{
get;
private set;
}
private Dictionary<Type, List<Ingredient>> ingredients = new Dictionary<Type, List<Ingredient>>();
static IngredientStore()
{
Current = new IngredientStore();
}
public void Register(Type type, List<Ingredient> ingredients)
{
this.ingredients[type] = ingredients;
}
public bool Uses(Type type, Ingredient ingredient)
{
// TODO: check the type is registered
return this.ingredients[type].Contains(ingredient);
}
}
public class Food
{
public bool Uses(Ingredient ingredient)
{
return IngredientStore.Current.Uses(this.GetType(), ingredient);
}
}
public class Cake : Food
{
static Cake()
{
IngredientStore.Register(typeof(Cake), new List<Ingredient>
{
Ingredient.Butter,
Ingredient.Eggs,
Ingredient.Flour,
};
}
}
public class CherryCake : Cake
{
static CherryCake()
{
IngredientStore.Register(typeof(CherryCake), new List<Ingredient>
{
Ingredient.Butter,
Ingredient.Eggs,
Ingredient.Flour,
Ingredient.Cherries,
};
}
}
精彩评论