2009-06-18 11 views
6

私はちょうどJava 7 preview presentation (pdf)を読んでいたし、連鎖呼び出しにスライドがあった。スライドに使用されている例は次のとおりです。Java 7の連鎖呼び出しですか?

// 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()を書くこともそれほど便利ではありません。

今、私はデルファイの世界からJavaに来ています。また、Delphiにはwith言語構成があります。これはいくつかのことを大切にしており、多くの人に嫌われています(あるいは、それは逆ですか?)。私はwithが呼び出されたオブジェクトへの参照を返すvoidメソッドに基づいて動作すると信じています - これはvoidが返すべきであると私が気に入らない部分ですなし)。

私は、Javaで採用されてwith言語機能をいただければ幸いですので、コード例がそうのように書くことができます。

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

は、私は、連鎖呼び出しにこのソリューションを好むだろう唯一のでしょうか?誰もがwithがJava言語の便利な拡張機能になると感じていますか? (「Java ++」の必要性に関する誰かの質問を思い出させます...)

+2

これはJava 7に限定されず、単にメソッドの "this"を返すことでBuilderを作成できます。良い例はjava.lang.StringBuilderです。 –

+5

私は、Java 7はこれを返さずに連鎖を許可しているため、メソッド呼び出しのセマンティクスを変更することが重要だと思います。 – OregonGhost

答えて

12

声明では、初期化子との匿名クラスを使用してJavaで翻訳することができます。

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

このイディオムを使用しての欠点はよくhereを文書化されています。

連鎖呼び出しは、メソッド連鎖の別名です。これはよく知られているイディオムで、Javaのいずれかのバージョンで動作します。私はかなりそのフォームのwith文のよう

class ChainedJava7 { 

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

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

あなたの答えが現れたとき、私は二重ブレースの初期化について書いていました:-) –

+1

これは本当にいいです。 +1 –

+2

JDK7への小さな言語変更の締め切りは数ヶ月前になっています。 –

1

私はwithのこのファンのファンではありません。私はPython with statementが好きです。私はあなたに同意するvoidvoidを意味するはずです。あなたが提供する例では、人が本当にメソッド呼び出しを連鎖できるようにしたいのであれば、メソッドの戻り値の型を連鎖可能にするだけでよい。

+0

ええと、それは無効です。プロデューサーとしては何も返さず気にせず、消費者は何かを受け取る気にはなりません(時にはそうすることもあります)。なぜあなたは気にする必要がありますか?意味的には何も変わりません(それほどタイプする必要はありません)。 –

+0

あなたが*何かを返すことを除いて、あなたはそれを暗にしています。あなたが何かを返さなかったなら、あなたはその上でメソッドを呼び出すことができませんでした。これはJavaであり、他のすべてが明示的なので、私はむしろ明白であると思います。 –

2

Thisがお勧めです

2

が、私はのVBのバージョンを好む:JDK 7のための

class Chained { 

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

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

提案がallowing of chaining method also for void return typeですそれら:

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

Withブロックの各属性は、まだあなたがそのyou'rを知っ.が先行しなければならないので例えば、ローカル変数ではなく、Objectプロパティを参照し、名前空間の衝突を減らします。

私たちはあなたの例を取る場合:

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

withSalt()DrinkBuilderの方法、またはローカルクラスのメソッドがある場合に指示する簡単な方法はありません。 with -edオブジェクトのメソッドがブロックwithにしか許可されていない場合、それらはあまり役に立たなくなると思います。

+0

私の提案はwithSalt()がDrink Builderのメソッドになることです。アプリケーションが必要な処理を行っていないことがわかった場合は、this.withSalt()を呼び出すことができます。どのオブジェクトのwithSalt()メソッドを呼び出さなければならないかを明示的にする。 –

1

多分、1つのオブジェクトに対する多くの呼び出しが、いくつかのコードを移動する必要があるというサインですか?

+2

いいえ、Javaはファーストクラスのプロパティを持たないため、これはDo OneのBean Mantra全体の一部です。そのため、ゲッターとセッターをすべて作成する必要があります。それが理由です。 Java 7(プロパティ)から削除されたもの。 –

+0

@darthcoder - あなたはそれを述べてうれしい!私はなぜこれが1.0以降Javaの一部ではないのか理解できません –

1

Joshua Bloch in Effective Java多くの引数を持つコンストラクタを使用する場合は、Builderの使用を強くお勧めします。 1つの理由は、構築されたオブジェクトが常に一貫した状態にあることを保証するために書かれているということです。また、ビルドされたオブジェクトのクラスに複雑な「入れ子構造のコンストラクタ」があるのを避けます。さらに別のことは、構築されたオブジェクトを不変(例えば、スレッドの安全性)にするには、セッターメソッドを持つことができないということです。

関連する問題