I followed this pattern to implement method chaining with subclasses in Java. The goal is that I have a method on a superclass, but can assign the subclass, like:
interface Screen {
<T extends Screen> T setBrightness(int value);
<T extends Screen> T setContrast(int value);
}
class CrtScreen implements Screen {
@SuppressWarnings("unchecked")
@Override
public <T extends Screen> T setBrightness(int value) {
// ...
return (T) this;
}
@SuppressWarnings("unchecked")
@Override
public <T extends Screen> T setContrast(int value) {
// ...
return (T) this;
}
}
class ColorCrt extends CrtScreen { /* ... */ }
public static void main(String[] args) {
ColorCrt cc = new ColorCrt().setBrightness(50).setContrast(50);
}
Now I also have container objects that I want to add my objects to, like:
class Stuff {
Stuff add(Screen s) {
// ...
return this;
}
Stuff add(String s) {
// ...
return this;
}
Stuff add(int i) {
// ...
return this;
}
}
public static void main(String[] args) {
new Stuff().add(new ColorCrt().setBrightness(50).setContrast(50)).add(25).add("...");
}
This now does no longer work in Java 8, giving me The method add(Screen) is ambiguous for the type Stuff. I understand the reason as explained here. I only see two options at the moment:
I don’t use
<T extends
, but justScreen setBrightness(value)
. It takes me the option to assign my implementing class to an according variable, and I have to cast it when I want to execute an implementation-specific method.I have to add casts or type parameters in my method chaining. This is very ugly to read and hard to fix for large constructs (many levels of boxing) that have to be ported from Java 7.
Is there a way to implement method chaining in Java 8 so that I still have both features? If not, can one of the both approaches be considered more intended?