要求
我正在尝试编写Observer
/ Observable
对类。我想参数化Observer
,以便可以进行类型安全更新调用。想象一下这个版本:
class View implements Observer<Model> {
@Override
public void update(Model model) { render(model); } // no casting:)
}
而不是需要强制转换的版本:
class View implements Observer {
@Override
public void update(Object model) { render((Model) model); } // casting:(
}
尝试
这是我到目前为止所拥有的。我的Observer
界面:
public interface Observer<T extends Observable> {
public void update(T observable);
}
和我的Observable
抽象类:
import java.util.List;
public abstract class Observable {
private List<Observer<? extends Observable>> observers;
public Observable() {
System.out.println(this.getClass());
}
public void addObserver(Observer<? extends Observable> obs) {
observers.add(obs);
}
public void removeObserver(Observer<? extends Observable> obs) {
observers.remove(obs);
}
protected <E extends Observable> void updateObservers(E self) {
for (Observer<? extends Observable> obs : observers) {
obs.update(self); // <-------------------- COMPILER ERROR!!!
}
}
}
问题
标有&#34; COMPILER ERROR&#34; .update()
:
Observer类型中的方法更新(捕获#4-of?extends Observable)不适用于参数(E)
因此,即使传递给self
的{{1}}参数的类型为update()
,它也不满足E extends Observable
所在的接口方法签名update(T observable);
。这是为什么?我真的希望那些兼容。
我可以解决这个问题以满足我的要求吗?
感谢。
答案 0 :(得分:9)
使用 import io.reactivex.Observable;
而不是 import java.util.Observable;答案 1 :(得分:4)
为什么?我真的希望那些兼容。
因为函数public void update(T observable);
与T
类具有相同的泛型参数Observer<T extends Observable>
,这意味着它的参数类型应该与引用的类型相同将调用update()
函数的变量。
然而,当您尝试使用通配符?
时,变量obs
的类型为Observer<? extends Observable>
,它可以是扩展Observable
的任何不同类型方法参数是E
。
我可以解决这个问题以满足我的要求吗?
是的,使用 Self Bound / Recursive Generics ,一个具体的例子就是Class Enum<E extends Enum<E>>
,要理解这个概念你可以看一下参见以下部分。
因此,您的Observable
将类似于:
import java.util.List;
public abstract class Observable<T extends Observable<T>> {
private List<Observer<T>> observers;
public Observable() {
System.out.println(this.getClass());
}
public void addObserver(Observer<T> obs) {
observers.add(obs);
}
public void removeObserver(Observer<T> obs) {
observers.remove(obs);
}
protected void updateObservers(T self) {
for (Observer<T> obs : observers) {
obs.update(self);
}
}
}
Observer
界面:
public interface Observer<T extends Observable<T>> {
public void update(T observable);
}
View
类:
class View implements Observer<Model> {
@Override
public void update(Model model) { render(model); }
}
假设您的Model
类应该是这样的:
public class Model extends Observable<Model>{
}
另见:
答案 2 :(得分:2)
根据@ hexafraction的评论,
Observable的观察者列表由Observer的任何子类(通配符<? extends Observer>
)参数化。这与Observer<T extends Observable>
的{{1}}方法不太匹配,该方法期望完全观察者参数化的Observable类型。
这是一个反例:A类扩展Observable,B类扩展Observable,A1类扩展A. obs的通配符允许Observer分配给obs,在这种情况下调用obs.update()实例A1无效。
解决方案也是对Observable类进行参数化,以便对Observer update(T observable)
方法正确约束List内容:
update()
观察者通过自己的public abstract class Observable<E> {
private List<Observer<E>> observers;
public Observable() {
observers = new ArrayList<>();
}
public void addObserver(Observer<E> obs) {
observers.add(obs);
}
public void removeObserver(Observer<E> obs) {
observers.remove(obs);
}
protected void updateObservers(E self) {
for (Observer<E> obs : observers) {
obs.update(self);
}
}
}
:
T
如果您需要类型约束,以便Observers 仅观察Observables,和/或Observables可能仅将Observables发送到Observer更新,则使用这些类签名:
public interface Observer<T> {
public void update(T observable);
}
类主体和行为不受影响,但如果Observers和Observables彼此绑定,编译器会抱怨。
通过Observable(模型)参数化观察者(视图):
public interface Observer<T extends Observable<T>> { ... }
public abstract class Observable<E extends Observable<E>> { ... }
自行参数化Observable(模型)并调用class View implements Observer<Model> {
@Override
public void update(Model model) { render(model); } // no casting:)
}
:
updateObservers()
答案 3 :(得分:0)
更改Observer界面,如下所示:
public interface Observer<T extends Observable> {
public <E extends Observable> void update(E observable);
}