我希望在 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);
}
}
}
A 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
的监听器定义中类(class)。我尝试了几种组合,但都没有奏效,因为对象无法放入列表中,或者调用不起作用。更改 Listener 类的定义 - 但如何更改?
定义
GenericCommand
以不同的方式进行分类,以便它始终使用对完全正确类型的监听器的引用:public abstract class GenericCommand<T> implements Future<T> { private final List<GenericCommandListener<MyExactTypeEvenIfSubclassing>> listeners = ...; }
这样
QueryValueCommand
从它派生接受GenericCommandListener<QueryValueCommand>
?
最佳答案
正如 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);
关于java - Java 中类型泛型的复杂案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26343445/