我几天都想弄清楚是否有可能,但我失败了,但也许有可能(我认为应该可行)。
假设我们有一些类似于Swing层次结构的UI组件+我们将使用流畅的接口Fluent Interfaces:
public abstract class Component {
...
public abstract Component setName(String name);
public abstract String getName();
...
}
public abstract class Panel extends Component {
....
}
public abstract class TitledPanel extends Panel {
....
public abstract TitledPanel setTitle(String title);
public abstract String getTitle();
}
是否可以使用泛型来编写类似的内容?
new TitledPanel().setName("panel").setTitle("Title);
setName应返回TitledPanel而不是Component,以便能够链接这些调用。
这只是一个简单的例子,但我的想法是,一旦我有一个类型为T的对象,任何调用超类的任何流体方法都会返回类型T.
编辑1:我忘了通过覆盖方法排除部分并返回协变类型:)我想要简单的泛型,如果可能的话。
答案 0 :(得分:2)
首先,我建议只使用set方法,然后删除该设置。
您可以使用协变返回类型,但这意味着覆盖每个派生类中的每个方法。但是,它确实涉及很多非常繁琐的代码。
public abstract class Component {
...
public Component name(String name) {
this.name = name;
return this
}
}
public abstract class Panel extends Component {
...
public Panel name(String name) {
super.name(name);
return this;
}
}
添加通用THIS
参数(作为枚举)使实现更容易,但客户端代码可能需要在声明中添加<?>
。
public abstract class Component<THIS extends Component<THIS>> {
...
protected abstract THIS getThis();
...
public THIS name(String name) {
this.name = name;
return this
}
}
public abstract class Panel<THIS extends Panel<THIS>> extends Component<THIS> {
...
}
public class TitledPanel extends Panel<TitledPanel> {
...
public TitledPanel getThis() {
return this;
}
}
另一种方法是使用Double Brace Idiom。
new TitledPane() {{
name("panel");
title("Title");
}}
答案 1 :(得分:1)
我不确定你是否可以通过泛型实现这一目标。你能做的就是这样:
public abstract class Component {
private String name;
public Component setName(String name) {
this.name = name;
return this;
}
public String getName() {
return name;
}
}
public abstract class Panel extends Component {
}
public class TitledPanel extends Panel {
private String title;
public TitledPanel setTitle(String title) {
this.title = title;
return this;
}
@Override
public TitledPanel setName(String name) {
super.setName(name);
return this;
}
public String getTitle() {
return title;
}
}
现在new TitledPanel().setName("panel").setTitle("Title");
可以使用
答案 2 :(得分:1)
在你的TiltedPanel中(顺便说一句,如果你想要新的那个,那就不能抽象),你可以覆盖Component中的抽象方法并更改返回类型。返回类型不是方法签名的一部分,因此您可以使用不同的返回类型实现它:
public class Test
{
public static void main(String[] args)
{
TiltedPanel p = new TiltedPanel().setName("panel").setTitle("title");
System.out.println("name = " + p.getName());
System.out.println("title = " + p.getTitle());
}
}
abstract class Component
{
public abstract Component setName(String name);
public abstract String getName();
}
abstract class Panel extends Component
{
}
class TiltedPanel extends Panel
{
private String title;
private String name;
public TiltedPanel setName(String name)
{
this.name = name;
return this;
}
public String getName()
{
return this.name;
}
public TiltedPanel setTitle(String title)
{
this.title = title;
return this;
}
public String getTitle()
{
return this.title;
}
}