2011-10-09 62 views
2

我有一個類,如:我怎麼能有一種虛擬靜態成員在C#

public class Food 
{ 
    public static IList<Ingredient> ingredients 
    public bool uses(Ingredient i) 
    { 
    return ingredients.Contains(i); 
    } 
} 

然後我繼承它使各種食品中,如:

public class Cake : public Food 
{ 
    public static IList<Ingredient> ingredients = new List<Ingredient>() 
    { 
    Sugar, 
    Eggs, 
    Milk 
    } 
} 

現在我希望能夠做到

Food f = getFood(); 
if (f.uses(Eggs)) 
{ 
    // Do something 
} 

所以我想有(例如)所有月餅可以共享成份的靜態列表,而不是一個列表PE r實例的Cake並能夠以虛擬方式訪問它。

如果需要,我願意激起代碼來獲得類似的效果!

+1

@Gtevil爲什麼你必須讓你列表'static'? – 2011-10-09 16:32:59

+0

此外,'C#'中沒有'public'或'private'繼承。所有繼承必須是「公共」的。 – 2011-10-09 16:53:09

+0

@ Mr.DD我希望列表是靜態的以節省內存並避免不必要的列表初始化,我只需要在應用程序啓動時執行一次,而不是每個實例一次。是的 - 我不需要那裏的公共遺產,可能每天都有太多的工作潛入! –

回答

4

在這種情況下,OOD「喜歡」,使類Food抽象的,因爲「成分」將是從Food到另一個不同。因此,正如其他人所指出的,製作此列表static是沒有意義的,因爲static應該是對由對象不區分的屬性的修飾符。

我提出一個解決方案如下:

public abstract class Food 
{ 
    public abstract IList<Ingredient> Ingredients 
    { 
     get; 
    } 
} 

現在任何類 - 是一個具體的 - 將從Food驅動,因此,這樣它給自己的,必須實現此屬性ingredients

public class Cake : Food 
{ 
    public override IList<Ingredient> Ingredients 
    { 
     get { 
       return new IList<Ingredient>() 
       { Sugar, Eggs, Milk }; 
      } 
    } 
} 
2

你可以定義一個方法GetIngredients()的子類覆蓋:

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

雖然只讀屬性會比方法更好。 – svick

0

有關使所有一類的這種情況下,怎麼樣?像:

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 }); 
+0

那不會編譯。你不能像這樣使用數組初始化器。集合初始值設定項需要集合的類型。 – svick

+0

@svick:所以使用一個正常的列表初始化程序......自從我使用C#以來已經很長時間了。 – Dani

0

配料不需要是靜態的。你可以有各種不同的蛋糕從蛋糕類派生,讓他們繼承常見的成分:

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 
     } 
    } 
} 
+0

我想使用靜態的想法是,對於同一類的所有實例,成分始終保持不變。 – thumbmunkeys

0

你真的不能,如果你的目標是讓每個類型的成分之一集合。我認爲你能做的最好的,但不是我不一定建議,是負責任移動到另一個類,像這樣:

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