2010-06-01 6 views
1

У меня есть классы, как показано ниже.Классы проектирования/интерфейс для поддержки методов, возвращающих разные типы

public interface ITest <T> 
{ 
    public Set<T> methodHere(); 
} 

public class test1 implements ITest<String> 
{ 
    Set<String> methodHere(){ 
     return // Set of String 
    } 
} 

public class test2 implements ITest<Integer> 
{ 
    Set<Integer> methodHere(){ 
    return // Set of Integer 
    } 
} 

public class ITestFactory { 
public static ITest getInstance(int type) { 
    if(type == 1) return new test1(); 
    else if(type == 2) return new test2(); 
} 
} 
public class TestUser { 
    public doSomething(int type) { 
     ITest t = ITestFactory.getInstance(type); 
     if(type == 1) Set<Integer> i = t.methodHere(); 
     else if(type == 2) Set<String> s = t.methodHere(); 
     ... 
    } 
} 

В заводском классе есть предупреждение о том, что ITest используется как необработанный тип. Какую модификацию я должен сделать, чтобы избавиться от нее?

Код TestUser выглядит уродливым. Я что-то пропустил? Я не хочу использовать Set<?>

Благодарности Найн

ответ

3

Вы можете вернуть ITest<?>, чтобы избавиться от предупреждения, но, вероятно, вы хотите более сильно ввести ПОДХОД:

public class TestFactory { 
    public static ITest<?> getInstance(int type) { 
     if(type == 1) 
     return new test1(); 
     else if(type == 2) 
     return new test2(); 
     else 
     throw new IllegalArgumentException("Unknown type"); 
    } 

    public static <T> ITest<T> getInstance(Class<T> clazz) { 
     if(clazz == String.class) 
     return new test1(); 
     else if(clazz == Integer.class) 
     return new test2(); 
     else 
     throw new IllegalArgumentException("Unknown type"); 
    } 
} 
+0

Хотя это хороший ответ, комментарий от @Thirler «Когда вы вызываете getInstance, невозможно узнать, какой тип будет возвращен» заставил меня задуматься над моим дизайном. Я не использую generics, но создал чистую иерархию классов. – Nayn

+0

Обновлен мой вопрос. Я все еще не здесь. – Nayn

0

В вашем случае это не имеет смысла для замены параметра дженериков, что будет на самом деле быть любого конкретного использования, однако вы можете добавить либо <Object> или <?> к сигнатуре метода, чтобы избавиться от предупреждения.

Большая проблема с примером кода, который я вижу, заключается в том, что вы не следуете JCC при наименовании своих классов и методов.

+0

Спасибо. Я выполнил правильный JCC в своем действительном коде. – Nayn

0

Когда вы вызываете getInstance, невозможно ввести knwo, тип которого будет возвращен.

Вы можете однако изменить подпись метода фабрики использовать дженерики:

public <A> ITest<A> getInstance(Class<A> type) 
{ 

} 
+0

Это не поможет напрямую, так как он использует 'int' для указания типа. Он мог бы, конечно, заменить 'int' на пару проверок' instanceof'. – Esko

+0

Да, очевидно, что реализация должна измениться. Но реальное изменение заключается в том, что вызывающий метод должен знать тип, который будет возвращен. – Thirler

+0

Да. Наверное, мы оба правы? :) – Esko

0

Нет шанс - кроме как от подавляя само предупреждение. В Java вообще невозможно объявить методы, которые имеют только другой тип возвращаемого значения. И нет «побега», используя дженерики. Методам с тем же именем, которые должны возвращать разные типы, нужна другая сигнатура аргумента (см. Перегрузку).

Если вы посмотрите на соответствующий байт код, вы обнаружите, что MethodHere вернет объект. Это называется тип erasure. Общий параметр используется только компилятором для проверки/обеспечения безопасности типа.

Как всегда - возвращает общий супертип, и вызывающий метод определяет тип объекта (например, используется в шаблоне адаптера).

Смежные вопросы