سؤال

Simply put, I have the following code, is there any better way to do this?

Also, I cannot modify any of the recipe classes.

public static ShapelessRecursiveRecipe convertRecipe(Object o)
{
    //might be a better way to do this
    if(o instanceof ShapedRecipes)
        return new ShapelessRecursiveRecipe((ShapedRecipes)o);
    else if(o instanceof ShapelessRecipes)
        return new ShapelessRecursiveRecipe((ShapelessRecipes)o);
    else if(o instanceof ShapedOreRecipe)
        return new ShapelessRecursiveRecipe((ShapedOreRecipe)o);
    else if(o instanceof ShapelessOreRecipe)
        return new ShapelessRecursiveRecipe((ShapelessOreRecipe)o);
    else
        return null;
}
هل كانت مفيدة؟

المحلول

The only alternative I can think of is fairly convoluted and involves reflection. You could place the valid classes in a set:

private static final Set<Class<?>> validClasses = new HashSet<Class<?>> ();

static {
    Collections.addAll(validClasses, ShapedRecipes.class,
                                     ShapelessRecipes.class
                                     ShapedOreRecipe.class); //etc.
}

Then you can replace the instanceof with something like:

if (o != null && validClasses.contains(o.getClass())) {

Finally the cast can't be done directly but you could use reflection to access the appropriate constructor:

Constructor<ShapelessRecursiveRecipe> constructor =
             ShapelessRecursiveRecipe.class.getConstructor(o.getClass());
constructor.newInstance(o);

I have not tested it but it should work.

Whether it makes your code better is debatable - probably not.

نصائح أخرى

If you can't modify the base classes, then I think the above is a suitable practical solution.

If you name your classes consistently, then you could get the original classname thus:

String classname = o.getClass().getClassName();

and then instantiate a new class using

Class.forName(classname + "MyVersion").newInstance();

(say) having a new class instance of your type for every input variant, and set the original object reference using a method in a common base class. But whether you want to do this depends on how many variants you have, and/or how likely that set is to change in the future.

I wouldn't return null, however, if you don't find a match. I'd rather throw an explicit exception.

If you have all your Recipes-classes derive from a base class Recipe, then you can have as parameter a Recipe reference:

public static ShapelessRecursiveRecipe convertRecipe(Recipe o)
{
return new ShapelessRecursiveRecipe(o);
}

You can check for the type of the Objects then in Constructor, or if you call only methods of them, polymorphysm calls the method of each subClass automatically.

Another way, not sure if this seriously better is to use generics like the following...

static <T extends ShapedRecipes>  ShapelessRecursiveRecipe convertRecipe(T obj) {
  return new ShapelessRecursiveRecipe(obj);
}

static <T extends ShapelessRecipes> ShapelessRecursiveRecipe convertRecipe(T obj) {
  return new ShapelessRecursiveRecipe(obj);
}

static <T extends ShapedOreRecipe> ShapelessRecursiveRecipe convertRecipe(T obj) {
  return new ShapelessRecursiveRecipe(obj);
}

static <T extends ShapelessOreRecipe> ShapelessRecursiveRecipe convertRecipe(T obj) {
  return new ShapelessRecursiveRecipe(obj);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top