我想在这里实现的是由子类决定是否要将java.lang.String或java.util.HashMap作为参数传递给query()方法。接口只需要声明子类必须实现查询方法,但我不关心什么类型的参数子类想要传入。
我有一个界面:
interface A<T>{
public void query(T type);
}
两个子类,如:
public class B implements A<String> {
public void query(String type);
}
public class C implements A<HashMap> {
public void query(HashMap type);
}
然后我有一个工厂类来生产B或C:
public class AFactory {
public static A<?> getType(String type) {
if(type.equals("B")){
return new B();
} else if(type.equals("C")) {
return new C();
}
}
}
这个想法是客户端可以使用如下界面,而不依赖于B,C,如:
A instance = AFactory.getType("B");
String a = "test";
instance.query(a);
我遇到的问题是:eclipse在instance.query(a)行上给出了错误:
类型A中的方法查询(捕获#2-of?)不适用于参数(String)。
我认为问题在于接口契约不知道查询应该是期望String还是HashMap。我只能想到解决这个问题的方法是,我必须将结果转换为:
B instance = (B)AFactory.getType("B");
String a = "test";
instance.query(a);
但是通过这样做,我将依赖于B而不仅仅是A(接口),这是我想在开始时避免的。我知道如何在不依赖子类的情况下做到这一点(在本例中为B和C)。
答案 0 :(得分:6)
正如欧内斯特所说,你需要投射返回的值 - A<String>
比A<?>
更具体。
如果您愿意更改工厂方法的签名,可以使用泛型来避免自己投射:
public static A<T> getType(Class<T> type) {
if (type.equals(String.class)) {
return new B();
} else if (type.equals(HashMap.class)) {
return new C();
}
}
然后您的调用代码可能如下所示:
A<String> instance = AFactory.getType(String.class);
String a = "test";
instance.query(a);
如果你不能这样做,那么getType()
的来电者必须投出。
答案 1 :(得分:1)
您不必投射到B
- 施放到A<String>
。这将为您提供query(String)
,但不会在您的来源中引入B
:
@SuppressWarnings("unchecked")
A<String> instance = (A<String>) AFactory.getType("B");
String a = "test";
instance.query(a);
我添加了@SuppressWarnings
注释,因为如果没有它,你会收到“不安全”的警告;你知道这个警告是虚假的,所以注释是可以的。