键入安全通用Java观察器编译时错误

kdb*_*man 6 java generics design-patterns type-safety observer-pattern

要求

我正在尝试写一对Observer/ Observable类.我想参数化,Observer以便可以进行类型安全更新调用.想象一下这个版本:

class View implements Observer<Model> {
    @Override
    public void update(Model model) { render(model); }  // no casting:)
}
Run Code Online (Sandbox Code Playgroud)

而不是需要强制转换的版本:

class View implements Observer {
    @Override
    public void update(Object model) { render((Model) model); }  // casting:(
}
Run Code Online (Sandbox Code Playgroud)

尝试

这是我到目前为止所拥有的.我的Observer界面:

public interface Observer<T extends Observable> {
    public void update(T observable);
}
Run Code Online (Sandbox Code Playgroud)

和我的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!!!
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题

标有"COMPILER ERROR"的行有一个问题.update():

Observer类型中的方法更新(捕获#4-of?extends Observable)不适用于参数(E)

因此,即使self传递给的参数update()是类型E extends Observable,它也不满足接口方法签名update(T observable);所在T extends Observable.这是为什么?我真的希望那些兼容.

我可以解决这个问题以满足我的要求吗?

谢谢.

小智 12

使用import io.reactivex.Observable;

而不是导入java.util.Observable;


Tar*_*rik 4

这是为什么?我真的希望它们能够兼容。

因为函数具有与类public void update(T observable);相同的泛型参数,这意味着它的参数类型应该与将调用该函数的引用变量的类型相同。TObserver<T extends Observable>update()

然而,当您尝试使用通配符时?,变量的类型obs可以是与方法参数的类型Observer<? extends Observable>扩展的任何不同的类。ObservableE

我可以解决这个问题以满足我的要求吗?

是的,使用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);  
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

界面Observer:

public interface Observer<T extends Observable<T>> {
    public void update(T observable);
}
Run Code Online (Sandbox Code Playgroud)

班上View:

class View implements Observer<Model> {
    @Override
    public void update(Model model) { render(model); } 
}
Run Code Online (Sandbox Code Playgroud)

假设你的Model类应该是这样的:

public class Model extends Observable<Model>{

}
Run Code Online (Sandbox Code Playgroud)

也可以看看: