开发者

How can I have a kind of virtual static member in c#

开发者 https://www.devze.com 2023-04-11 23:58 出处:网络
I have a class like: public class Food { public static IList<Ingredient> i开发者_开发百科ngredients

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号