As discussed with @SimonAndréForsberg, programming too defensively is often an unnecessary waste of time, and we should trust our own declarations.
However, for the fun of it, here is a solution to enforce all the restrictions you want on class/interfaces declarations at compile time.
Declarations
The View
interface:
public interface View<T extends Viewable<T, ?>> {}
Here, we just want to ensure that the type parameter is a
Viewable
.The second type argument does not need restriction, because the declaration of
Viewable
would not allow aViewable<T,?>
to exist if the?
were not itself aView<T>
.
The Viewable
interface:
public interface Viewable<T extends Viewable<T,?>, V extends View<T>> {
public void addViewCallback(final V view);
public void removeViewCallback(final V view);
}
- Here,
T
needs to be declared as aViewable
because we use it as type parameter forView<T>
at the end of the line. - Same as before, no restriction needed on
?
because we say right after that the second type parameter needs to be aView<T>
if the first type parameter is aT
.
Usage
public class Hand implements Viewable<Hand, HandView> {
@Override
public void addViewCallback(HandView view) {}
@Override
public void removeViewCallback(HandView view) {}
}
public interface HandView extends View<Hand> {
}