0

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

4 Answers4

0

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.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
0

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.

assylias
  • 321,522
  • 82
  • 660
  • 783
  • I'll just use introspection like in the original post. Out of the solutions posted, I liked this one the most. –  Aug 05 '13 at 09:52
0

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.

arjacsoh
  • 8,932
  • 28
  • 106
  • 166
0

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);
}
chitakasa
  • 243
  • 1
  • 6