1

我试图弄清楚是否可能,我失败了,但也许有可能(我认为应该有可能)。

假设我们有一些类似于 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:我忘了排除覆盖方法并返回协变类型的部分:)如果确实可能的话,我只想要普通的泛型。

4

3 回答 3

2

首先,我建议只使用 set 方法,然后删除 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参数,如枚举,使实现更容易,但客户端代码可能需要添加一个<?>in 声明。

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;
    }
}

另一种方法是使用双括号成语。

new TitledPane() {{
    name("panel");
    title("Title");
}}
于 2010-02-04T06:02:07.230 回答
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");可以工作

于 2010-02-04T06:01:58.267 回答
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;
    }
}
于 2010-02-04T06:03:44.143 回答