我想在Java中有一个以某种方式引用自身的类型。
确切地说,我想要一个可以拥有监听器的命令类:
public abstract class GenericCommand<T> implements Future<T> {
// ...
private final List<GenericCommandListener<GenericCommand<T>>> listeners = new ArrayList<>();
@SuppressWarnings("unchecked")
public void addListeners(
GenericCommandListener<GenericCommand<T>>... listeners) {
this.listeners.addAll(Arrays.asList(listeners));
}
private void onValueAvailable() {
for (GenericCommandListener<GenericCommand<T>> listener : listeners) {
listener.onValueAvailable(this);
}
}
}
GenericCommandListener
看起来像
public interface GenericCommandListener<T extends GenericCommand<?>> {
public void onValueAvailable(T theCmd);
}
此命令的目的是发送到设备并生成某种类型的结果。
现在,我希望能够覆盖我的GenericCommand<T>
,以便它实现一种特殊的命令,可能是FooCommand
,它会产生Double
:
public class QueryValueCommand extends GenericCommand<Double> {
}
现在,我创建了这个类的实例,并希望它接受GenericCommandListener<QueryValueCommand>
。但我不能这样做;我所能做的就是让它接受GenericCommandListener<GenericCommand<Double>>
。
我看到以下几种方式:
在? super
类的侦听器定义中执行? extends
或GenericCommand
的操作。我尝试了几种组合,但都没有工作,因为对象无法放入列表,或者调用不起作用。
更改Listener类的定义 - 但是如何?
以不同的方式定义GenericCommand
类,以便它始终使用对完全正确类型的侦听器的引用:
public abstract class GenericCommand<T> implements Future<T> {
private final List<GenericCommandListener<MyExactTypeEvenIfSubclassing>> listeners = ...;
}
以便从中派生的QueryValueCommand
接受GenericCommandListener<QueryValueCommand>
?
答案 0 :(得分:2)
正如aruisdante所提议的,班级GenericCommand
必须依靠自己:
public abstract class GenericCommand<C extends GenericCommand<C, T>, T> implements Future<T> {
// ...
private final List<GenericCommandListener<C, T>> listeners = new ArrayList<>();
@SuppressWarnings("unchecked")
public void addListeners(
GenericCommandListener<C, T>... listeners) {
this.listeners.addAll(Arrays.asList(listeners));
}
private void onValueAvailable() {
for (GenericCommandListener<C, T> listener : listeners) {
listener.onValueAvailable((C) this);
}
}
}
侦听器类也必须通过这种方式进行修改:
interface GenericCommandListener<C extends GenericCommand<C,T>, T> {
public void onValueAvailable(C theCmd);
}
现在,您可以声明:
public class QueryValueCommand extends GenericCommand<QueryValueCommand, Double>
你可以写:
QueryValueCommand command = new QueryValueCommand();
GenericCommandListener<QueryValueCommand, Double> listener = ...;
command.addListeners(listener);
答案 1 :(得分:0)
如果你这样实施GenericCommandListener
:
public interface GenericCommandListener<T> {
public <U extends GenericCommand<T>> void onValueAvailable(U theCmd);
}
然后你应该能够像这样添加你的GenericCommand
类的听众:
public abstract class GenericCommand<T> implements Future<T> {
private final List<GenericCommandListener<T>> list = new ArrayList<>();
public <U extends GenericCommandListener<T>> void addListener(U listener) {
list.add(listener);
}
这有帮助吗?