【发布时间】:2018-03-21 16:19:10
【问题描述】:
我跟着this pattern 用Java 中的子类实现了方法链接。目标是我在超类上有一个方法,但可以分配子类,例如:
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);
}
现在我还有一些容器对象,我想将我的对象添加到其中,例如:
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("...");
}
现在这在 Java 8 中不再有效,让我 方法 add(Screen) 对于 Stuff 类型不明确。我将原因理解为explained here。我目前只看到两个选项:
我不使用
<T extends,而只是使用Screen setBrightness(value)。我可以选择将我的实现类分配给相应的变量,当我想执行特定于实现的方法时,我必须强制转换它。我必须在方法链中添加强制类型转换或类型参数。这很丑 对于必须从 Java 7 移植的大型结构(许多级别的装箱),阅读起来很难修复。
有没有办法在 Java 8 中实现方法链接,以便我仍然拥有这两个功能?如果不是,是否可以认为这两种方法中的一种更有意义?
【问题讨论】:
-
class Screen<T extends Screen> {呢? -
我不太明白为什么
add(Screen)应该是模棱两可的。 -
@lexicore ... 因为
String的子类(假设String不是final)可能实现interface Screen。在编译时,编译器不知道运行时的对象是否可能是这样做的子类。 (编译器并不关心String实际上不能被子类化,因为它是final。)见这里:stackoverflow.com/q/28466925/1503237 -
鉴于 Java 支持协变返回类型,我认为根本没有理由使用泛型。
Screen可以声明Screen setBrightness(int),CrtScreen可以实现/覆盖该方法为CrtScreen setBrightness(int)。您的原始实现不是,也从来不是类型安全的。
标签: java generics java-8 method-chaining