質問

Java 7プレビュープレゼンテーション(pdf)を読んでいたところ、 Chained Invocation のスライド。スライドで使用されている例は次のとおりです。

// Construction with setters
DrinkBuilder margarita = new DrinkBuilder();
margarita.add("tequila");
margarita.add("orange liqueur");
margarita.add("lime juice");
margarita.withRocks();
margarita.withSalt();
Drink drink = margarita.drink();

// Construction with chained invocation
Drink margarita = new DrinkBuilder()
    .add("tequila")
    .add("orange liqueur")
    .add("lime juice")
    .withRocks()
    .withSalt()
    .drink();

そして、私はこれについて複雑な感情を持っています。 1つのステートメントに多くのメソッド呼び出しをチェーンしないでください。一方、 margarita.this() margarita.that()を記述することもあまり便利ではありません。

今、Delphiの世界からJavaに来ています。また、Delphiには with があります。言語構成。これは少数の人に大事にされ、多くの人に嫌われています(または逆ですか?)。 with は、連鎖呼び出しのアイデアよりもエレガントであると思います(呼び出したオブジェクトへの参照を返す void メソッドに基づいて動作すると思います) void nothing を返す必要があるため、これは私が好まない部分です。

Javaで採用されている with 言語機能に感謝するため、サンプルコードは次のように記述できます。

Drink margarita = null;
with (new DrinkBuilder()) {
    add("tequila");
    add("orange liqueur");
    add("lime juice");
    withRocks();
    withSalt();
    margarita = drink();
}

この呼び出しをチェーン呼び出しよりも好むのは私だけですか?他の人は、 with がJava言語の便利な拡張機能であると感じていますか? (" Java ++"の必要性に関する誰かの質問を思い出させます...)

役に立ちましたか?

解決

with with ステートメントは、初期化された匿名クラスを使用してJavaで翻訳できます:

Drink margarita = new DrinkBuilder() {{
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
}}.drink();

このイディオムを使用することのマイナス面は、こちらで十分に文書化されています。

Chained Invocationは、メソッドチェーンのエイリアスです。これはよく知られているイディオムであり、Javaのどのバージョンでも動作します。

class Chained {

    public Chained withFoo() { 
        // ...
        return this;
    }

    public Chained withBar() { 
        // ...
        return this;
    }
}    

JDK 7の提案は、 void戻り型にもチェーンメソッドを許可するです。

class ChainedJava7 {

    public void withFoo() { 
        // ...
    }

    public void withBar() { 
        // ...
    }
}    

他のヒント

これは興味を引くかもしれません。

その形式の with ステートメントは非常に好きですが、VBバージョンのステートメントが好きです:

With testObject
    .Height = 100
    .Text = "Hello, World"
    .ForeColor = System.Drawing.Color.Green
End With

With ブロックの各属性の前にを付ける必要があるため、たとえばローカル変数ではなく、Objectプロパティを参照していることがわかります。 、名前空間の衝突を減らします。

例を挙げると:

with (new DrinkBuilder()) {
    add(“tequila”);
    add(“orange liqueur”);
    add(“lime juice”);
    withRocks();
    withSalt();
    margarita = drink();
}

withSalt() DrinkBuilder のメソッドであるか、ローカルクラスのメソッドであるかを確認する簡単な方法はありません。 with ブロックで with -edオブジェクトのメソッドのみを許可する場合、それらははるかに有用でなくなると思います。

私は、この with の使用が好きではありません。 Pythonの with ステートメントが非常に好きです。ただし、 void void を意味することに同意します。あなたが提供する例では、メソッド呼び出しを本当に連鎖させたい人は、メソッドの戻り値の型を変更するだけで、連鎖可能になります。

1つのオブジェクトに対する多くの呼び出しは、一部のコードを移動する必要がある兆候でしょうか?

効果的なJava の項目#2では、多くの引数を持つコンストラクターがある場合のビルダー。 1つの理由は、ビルドされたオブジェクトが常に一貫した状態にあることを保証するために記述できるからです。また、複雑な「テレスコープコンストラクター」を避けることができます。ビルドされたオブジェクトのクラス内。さらにもう1つは、ビルドされたオブジェクトを不変(たとえば、スレッドの安全性)にしたい場合、セッターメソッドを使用できないことです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top