Reputation:
Preface: I've already researched why "enum inheritance" is illegal in Java.
My problem is the following: given a class Recipe
, I want its property category
to be a list of constant values like APPETIZER, BREAKFAST, DESSERT, MAIN_COURSE, SOUP
- I logically use enums for this.
My question then is: if I wanted each of this enums to have "children of their own" (for example: SWEET
and SAVORY
for BREAKFAST
, or CAKE
, MUFFIN
and BISCUITS
for DESSERT
), so that:
myRecipe.setCategory(DESSERT)
should raise an exception);SOUP.BISCUITS
should raise an exception);myRecipe.setCategory(DESSERT.CAKE)
) - or other similar "lightweight" syntax.I haven't been able to come up with any clean solution in Java to fit all three requisites.
Is there any "esoteric" design pattern for this? How would you implement this?
Upvotes: 3
Views: 133
Reputation: 1665
Create a class Category. Inside Category, declare all the enum classes.
public class Category
{
public enum APPETIZER
{
}
public enum BREAKFAST
{
SWEET,
SAVORY
}
public enum DESSERT
{
CAKE,
MUFFIN,
BISCUITS
}
public enum MAIN_COURSE
{
}
}
Inside the Recipe class, category should be of type DESSERT
. I have static imported Category class.
public class Recipe
{
DESSERT category;
public void setCategory(DESSERT category)
{
this.category = category;
}
public static void main(String[] args)
{
Recipe myRecipe = new Recipe();
myRecipe.setCategory(DESSERT.BISCUITS);
// statements below give compile time errors
// myRecipe.setCategory(DESSERT);
// myRecipe.setCategory(BREAKFAST.SWEET);
}
}
Convert Category into a marker interface. All the categories such as DESSERT
, BREAKFAST
, etc. should implement Category.
interface Category {}
enum APPETIZER implements Category
{
}
enum BREAKFAST implements Category
{
SWEET,
SAVORY
}
enum DESSERT implements Category
{
CAKE,
MUFFIN,
BISCUITS
}
enum MAIN_COURSE implements Category
{
}
Make Recipe generic.
public class Recipe <T extends Category>
{
T category;
public void setCategory(T category)
{
this.category = category;
}
public static void main(String[] args)
{
Recipe<DESSERT> myRecipe = new Recipe<>();
myRecipe.setCategory(DESSERT.BISCUITS);
// statements below give compile time errors
// myRecipe.setCategory(DESSERT);
// myRecipe.setCategory(BREAKFAST.SWEET);
}
}
These are not design patterns. They are self implementation.
Upvotes: 1
Reputation: 11494
You can do this:
class Recipe {
private final Meal meal;
private final MealCategory category;
public <T extends Meal> Recipe(T meal, MealCategory<T> category) {
this.meal = meal;
this.category = category;
}
}
abstract class Meal {}
class Breakfast extends Meal {}
class Dinner extends Meal {}
class MealCategory<T extends Meal> {}
class Cereal extends MealCategory<Breakfast> {}
class Meat extends MealCategory<Dinner> {}
public class Test {
public static void main(String[] args) {
Recipe r = new Recipe(new Breakfast(), new Cereal());
Recipe r2 = new Recipe(new Breakfast(), new Meat()); // compile time error
}
}
Upvotes: 1