我有一个通用的<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="Hotspot"></div>
<div class="Hotspot"></div>
<div class="Hotspot"></div>
界面:
Command
以及一些实施:
public interface Command<T> {
public void execute(T value);
}
我需要的是public class ChangeName implements Command<String>{
public void execute(String value) {...}
}
public class SetTimeout implements Command<Integer>{
public void execute(Integer value) {...}
}
来将命令名与特定的Map
对象相关联:
Command
显然,我在声明Map<String, Command> commands = new HashMap<>();
...
commands.put("changeName", new ChangeName());
时收到rawtypes
警告。
如果我使用问号,我最终会遇到编译错误:
Map
类型Command中的execute(capture#2-of?)方法不适用于参数(String)
我知道你不能拥有一个不可重复类型的类型安全异构容器( Effective Java 中的第29项),但解决这个问题的最佳方法是什么问题
答案 0 :(得分:1)
如果您从逻辑上考虑它,那么您的所有命令模板必须满足的最高通用接口是什么?
看看你的String,Integer的例子,看起来它不能只是Java Object。试试这个,
var swipeRight = new UISwipeGestureRecognizer((s) => { swiped(s); });
private void swiped(UISwipeGestureRecognizer s) {
Console.WriteLine("User swiped right");
}
修改强>: 基本上,您在声明时添加模板信息,但在使用时会想要完全删除它。这里有两个选择:
a)您不使用泛型,因为您无法将它们用于潜力。处理简单的Object类,而不是在特定的执行函数中,只测试正确的类型。
b)为不同类型创建不同的地图。通过这种方式,您可以将模板用于其潜力。
答案 1 :(得分:1)
我认为你需要让命令在运行时知道它们可接受的参数:
export CUDA_HOME='/usr/local/cuda'
export LD_LIBRARY_PATH='/usr/local/cuda/lib64'
# Override PATH
export PATH=${CUDA_HOME}/bin:${PATH}
现在使用代码将是这样的:
public abstract class Command<T> {
private final Class<T> argumentClass;
protected Command(Class<T> argumentClass) {
this.argumentClass = argumentClass;
}
public abstract <U extends T> void execute(U argument);
@SuppressWarnings("unchecked")
public final <U> Command<? super U> cast(Class<U> argumentClass) {
if (this.argumentClass.isAssignableFrom(argumentClass)) {
return (Command<? super U>) this;
} else {
throw new UnsupportedOperationException("this command cannot handle argument of type " + argumentClass.getName());
}
}
}
上面的抑制警告是令人讨厌的,因为演员必须始终为真,但是private <U> void executeCommand(final String name, final U arg) {
@SuppressWarnings("unchecked")
Class<U> clazz = (Class<U>) arg.getClass();
commands.get(name).cast(clazz).execute(arg);
}
的最终定义限制为返回getClass
。
地图可以输入为:
Class<?>
每个命令子类都将扩展抽象Map<String, Command<?>> commands = new HashMap<>();
类。
例如匿名内部类定义o stderr的打印字符串命令:
Command
独立版本:
final Command<String> printString = new Command<String>(String.class) {
public <U extends String> void execute(U arg) {
System.err.println(arg);
}
};
如果您愿意,可以提取public StdErrPrintCommand extends Command<String> {
public StdErrPrintCommand() { super(String.class); }
@Override
public <U extends String> void excecute(U arg) {
System.err.println(arg);
}
}
接口并将抽象类重命名为Command
。