我跟着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中实现方法链接,这样我仍然有两个功能?如果没有,那么这两种方法中的一种是否可以被更多地考虑?
答案 0 :(得分:0)
在您的代码中:
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;
}
}
您的成员函数setContrast和setBrightness不需要是通用的,如果它是通用的,您需要指定类型(在调用站点)。我使用这种方法,而不是使接口通用,这意味着方法不需要:
interface Screen<T extends Screen> {
T setBrightness(int value);
T setContrast(int value);
}
class CrtScreen implements Screen<CrtScreen> {
@SuppressWarnings("unchecked")
@Override
public CrtScreen setBrightness(int value) {
// ...
return this;
}
@SuppressWarnings("unchecked")
@Override
public CrtScreen setContrast(int value) {
// ...
return this;
}
}
如果您想按照自己的方式进行操作,则需要指定哪种类型适用于通用(见下文):
public static void main(String[] args) {
new Stuff()
.add(new ColorCrt().<ColorCrt>setBrightness(50))
.add(25).add("...");
}
答案 1 :(得分:0)
最后,我找到了一个适用于interface
和abstract class
的解决方案。这似乎足以满足Java 8编译器。
概念证明:
static abstract class Screen {
abstract <T extends Screen> T setBrightness(int value);
abstract <T extends Screen> T setContrast(int value);
}
static class CrtScreen extends 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;
}
}
static class ColorCrt extends CrtScreen { /* ... */ }
static 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) {
ColorCrt cc = new ColorCrt().setBrightness(50).setContrast(50);
new Stuff().add(new ColorCrt().setBrightness(50).setContrast(50)).add(25).add("...");
}