Say I have a bakery and an inventory of ingredients:
enum Ingredient {
case flower = 1
case sugar = 2
case yeast = 3
case eggs = 4
case milk = 5
case almonds = 6
case chocolate = 7
case salt = 8
}
A case's rawValue
represents the inventory number.
Then I have two recipes:
Chocolate Cake:
- 500g flower
- 300g sugar
- 3 eggs
- 200ml milk
- 200g chocolate
Almond Cake:
- 300g flower
- 200g sugar
- 20g yeast
- 200g almonds
- 5 eggs
- 2g salt
Now I define a function
func bake(with ingredients: [Ingredient]) -> Cake
Of course I trust my employees, but I still want to make sure they only use the right ingredients to bake a cake.
I could do this by defining two separate enums like this:
enum ChocolateCakeIngredient {
case flower
case sugar
case eggs
case milk
case chocolate
}
enum AlmondCakeIngredient {
case flower
case sugar
case yeast
case eggs
case almonds
case salt
}
and bake a cake like this:
// in chocolate cake class / struct:
func bake(with ingredients: [ChocolateCakeIngredient]) -> ChocolateCake
// in almond cake class / struct:
func bake(with ingredients: [AlmondCakeIngredient]) -> AlmondCake
But then I would have to redefine the same ingredients over and over again as many ingredients are used for both cakes. I really don't want to do that - especially as there are inventory numbers attached to the enum cases as rawValue
s.
That leads me to the question if there is a way in Swift to restrict an enum to certain cases of another enum? Something like (pseudo code):
enum ChocolateCakeIngredient: Ingredient {
allowedCases:
case flower
case sugar
case eggs
case milk
case chocolate
}
enum AlmondCakeIngredient: Ingredient {
allowedCases:
case flower
case sugar
case yeast
case eggs
case almonds
case salt
}
Is a composition like this possible? How can I do it?
Or maybe there is another pattern I can use for this scenario?
Update
From all the comments and answers to this question I figured that the example I picked for this question was a little inappropriate as it didn't boil down the essence of the problem and left a loophole regarding type safety.
As all posts on this page relate to this particular example, I created a new question on Stackoverflow with an example that's easier to understand and hits the nail on its head: