Design classes/interface to support methods returning different types
I have classes as below.
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();
...
}
}
There is a warning in the factory class that ITest is used as raw type. What modification should I do to get rid of it?
The TestUser code looks ugly. Am I missing something very basic? I don't want to use Set<?>
Thanks Nayn
You can return a ITest<?>
to get rid of the warning but probably you want a more strongly type aproach:
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");
}
}
In your case there isn't a meaningful replacement for the Generics parameter that would actually be of any specific use, however you can add either <Object>
or <?>
to the method signature to get rid of the warning.
The bigger issue with the example code I see is that you're not following JCC when naming your classes and methods.
When you call getInstance it is impossible to knwo which type will be returned.
You can however change the signature of the factory method to use generics:
public <A> ITest<A> getInstance(Class<A> type)
{
}
No chance - except from supressing the warning itself. In Java it's not possible in general to declare methods that only have a different return type. And there is no 'escape' by using generics. Methods with the same name that shall return different types need a different argument signature (see: overloading).
If you look at the corresponding byte code, you'll find that MethodHere
will return an Object. This is called type erasure. The generic parameter is only used by the compiler to check/assure type safety.
As always - return a common supertype and have the method caller determine the object type (like used in adapter pattern).
精彩评论