質問

I have

public class  MyFactory()
{
   public static <T> T getItem(Element element, Class<T> clazz)
   {
         T item = null;
         if (clazz == IFoo.class)
         {
              item =  (T) new Foo();
         }
         else if (clazz == IBar.class)
         {
              item =  (T) new Bar();
         }
         ...

        assert item instanceof IParsable;
        (IParsable(foo)).parse(element)

       return item;
   }

}

and then I call it like this

IFoo parsedFoo = MyFactory.getItem(someElement, IFoo.class);

Here the concrete classes implement IParsable . Would I be able to remove the runtime assert check and put a compile time check to see if 'IParsable' and call parse?

Also I was wondering if there is a way to enforce IFoo<-->Foo implements relationship at compile time in getItem() method and remove the typecasting (T) ?

EDIT: I thought I would give an outline for IFoo and Foo

public interface IFoo
{
    String getFooName();
    int getFooId();
    ....
}


class Foo implements IFoo, IParsable
{
      ...
}

EDIT2:

I just thought of a refactoring like this, now the only thing that's not a compile time check is the relation between interface and implementation.

  public static <U extends IParsable, T> T getItem(Element element, Class<T> clazz)
   {
         U item = null;
         if (clazz == IFoo.class)
         {
              item =  (U) new Foo();
         }
         else if (clazz == IBar.class)
         {
              item =  (U) new Bar();
         }
         ...

       item.parse(element)

       return (T) item;
   }
役に立ちましたか?

解決

Maybe something like this:

public static <T> T getItem(Element element, Class<T> clazz) {
    IParsable item = null;
    if (clazz == IFoo.class) {
        item = new Foo();
    } else if (clazz == IBar.class) {
        item = new Bar();
    }
    item.parse();
    return (T) item;
}

The fact that Foo is an IParsable is checked at compile time. The other cast (to (T)) is still a runtime exercise - but it was also the case in your example.

他のヒント

Here the concrete classes implement IParsable . Would I be able to remove the runtime assert check and put a compile time check to see if 'IParsable' and call parse?

From what I know - no, it's not possible. You will be passing object to this method at runtime, the compiler has no idea what objects will be passed. So compile time is not an option here. 

Also I was wondering if there is a way to enforce IFoo<-->Foo implements relationship at compile time in getItem() method and remove the typecasting (T) ?

Again, only at runtime with isAssignableFrom

you should register all the mappings at class setup time like this (it's ugly cause you can't check more than one bounds with the same type parameter):

private static Map<Class<?>, Class<?>> MAPPINGS = ...;

static {
  registerMapping(IFoo.class, Foo.class, Foo.class);
  // ...
}

private static <IT, TT extends IT, TP extends IParseable> void registerMapping(Class<IT> ifaceClazz, Class<TT> implClazz, TP parseableClazz) {
  MAPPINGS.put(ifaceClazz, implClazz);
}

then in getItem() your if block turns into a simple map lookup. note, this will not get rid of the (T) cast, but there's nothing you can do about that.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top