1

私は何日も可能かどうかを考えようとしていましたが、失敗しましたが、おそらく可能です(可能であるはずだと思います)。

Swing階層と同様のUIコンポーネントがいくつかあるとしましょう+流暢なインターフェースを使用します流暢なインターフェース

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はComponentではなくTitledPanelを返す必要があります。

これは単純な例ですが、T型のオブジェクトを取得したら、スーパークラスの流暢なメソッドを呼び出してT型を返すという考え方です。

編集1:メソッドをオーバーライドして共変型を返す部分を除外するのを忘れました:)可能であれば、単純なジェネリックスだけが必要です。

4

3 に答える 3

2

まず、セット メソッドのみを使用し、セットを削除することをお勧めします。

共変の戻り値の型を使用できますが、これは各派生クラスのすべてのメソッドをオーバーライドすることを意味します。ただし、非常に面倒なコードが多く含まれます。

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 に答える