2012-05-17 2 views
0

У меня есть следующий код:Java дженериков и интерфейсы, используя типы в качестве параметров метода

public interface IDoWork<K extends AbstractKey,V extends AbstractClass> { 
    V obtain(K key, V value); 
} 

public class AbstractKey { 
    String id; 
} 

public class AbstractClass { 
    String name; 
} 

public class ConcreteA extends AbstractClass { 
    String attributeA; 
} 

public class DoWorkA implements IDoWork<KeyA, ConcreteA> { 

    private static final DoWorkA INSTANCE = new DoWorkA(); 

    public static DoWorkA getInstance() { 
     return INSTANCE; 
    } 

    @Override 
    public ConcreteA obtain(KeyA k, ConcreteA v) { 
     //do something in real life 
     return null; 
    } 

} 

public class Main { 

    public static void main(String[] args){ 
     KeyA a = new KeyA(); 
     ConcreteA c = new ConcreteA(); 
     IDoWork<? extends AbstractKey, ? extends AbstractClass> instance = 
       WorkFactory.getInstance().obtainInstance(a); 
     instance.obtain(a, c); 
    } 
} 

public class WorkFactory { 

    private static final WorkFactory INSTANCE = new WorkFactory(); 

    public static WorkFactory getInstance() { 
     return INSTANCE; 
    } 

    public IDoWork<? extends AbstractKey, ? extends AbstractClass> obtainInstance(AbstractKey key){ 
     if(key instanceof KeyA){ 
      return DoWorkA.getInstance(); 
     } 
     throw new IllegalArgumentException("Case not handled"); 
    } 

} 

В следующем коде:

KeyA a = new KeyA(); 
ConcreteA c = new ConcreteA(); 
IDoWork<? extends AbstractKey, ? extends AbstractClass> instance = WorkFactory.getInstance().obtainInstance(a); 
instance.obtain(a, c); 

Эта строка не компилируется:

instance.obtain(a, c); 

из-за природы дженериков Java. Я получаю следующую ошибку:

The method obtain(capture#3-of ? extends AbstractKey, capture#4-of ? extends AbstractClass) in the type IDoWork is not applicable for the arguments (KeyA, ConcreteA)

Есть ли другой способ сделать это? Если опустить параметры типа в

IDoWork<? extends AbstractKey, ? extends AbstractClass> instance =... 

Если удалить параметры типа из IDoWork ... он работает, но я получаю предупреждение. Есть ли способ исправить это? Я знаю, что я могу удалить параметры типа из интерфейса, и это решит проблему, но я считаю нужным иметь генераторы, чтобы не делать кастинг +, это привносит ясность в код, так как ясно, что каждый класс использует. Depencendy инъекция из вопроса, поскольку он не доступен в кодовом я в

+1

Вы не можете использовать: 'IDoWork instance = WorkFactory.getInstance(). GetInstance (a);'? Что такое код в «WorkFactory» - что он связывает в качестве аргументов общего типа? –

+0

Я только что добавил класс WorkFactory. Спасибо –

ответ

0

У меня есть то, что работает, но не очень оптимально:.

Если вы определили ваш WorkFactory таким образом:

public class WorkFactory { 
    private static final WorkFactory INSTANCE = new WorkFactory(); 
    public static WorkFactory getInstance() { 
     return INSTANCE; 
    } 

    @SuppressWarnings("unchecked") 
    public <K extends AbstractKey, V extends AbstractClass> IDoWork<K, V> obtainInstance(K key, V val) { 
     if (key instanceof KeyA) { 
      return (IDoWork<K, V>) DoWorkA.getInstance(); 
     } 
     throw new IllegalArgumentException("Case not handled"); 
    } 

} 

тогда ваш главный метод должен работать чисто:

public static void main(String[] args){ 
     KeyA a = new KeyA(); 
     ConcreteA c = new ConcreteA(); 
     IDoWork<KeyA, ConcreteA> instance = WorkFactory.getInstance().obtainInstance(a, c); 
     instance.obtain(a, c); 
} 

Я изменил obtainInstance взять ключ и Валя, чтобы правильно выводить типы.

+0

Спасибо за ваш ответ, но в моем случае фабрика должна использовать только ключ, а не значение –

+0

. Следующий следующий код работает, но дает предупреждение: IDoWork instance = WorkFactory.getInstance(). GetInstance (a); Я хотел бы знать, как избавиться от этого предупреждения без @SuppressWarnings. –

+0

Он должен по-прежнему работать, даже если вы удалите значение из подписи, он выведет тип на основе LHS –