2012-01-11 3 views
12

Clojureを使用して、次のオブジェクトを作成するにはどうすればよいですか?オブジェクトは、(効果的なJavaから)Javaコードから取られている:私はClojureのから始まるんだけど、それは私には、標準的なメソッド呼び出しのように見えますClojureでビルダーパターンを使用するJavaライクなオブジェクトを作成するにはどうすればよいですか?

NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();

答えて

21

..が多少出て下落していますより汎用性の高い->に置き換えられました。個人的に私は好む:

(-> (NutritionFacts$Builder. 240 8) 
    (.calories 100) 
    (.sodium 350) 
    (.carbohydrates 27) 
    (.build)) 

それは夫婦以上の文字ですが、あなたは二つのもの得る:

  • 明示します。 .がすぐそこにあるので、私はナトリウム線(例えば)を見て、それがJavaメソッド呼び出しだと言うことができます。
  • 柔軟性。私が必要な場合は、途中で非メソッド呼び出しを連鎖させることができます(stdoutにそれを表示します)。または、この最後の部分で、他の関数呼び出しに送ります。

最も重要なのは、この質問に対する他のすべての答えはクラス名を間違っを得ている:JavaのNutritionFacts.BuilderはNutritionFacts $ビルダーという名前の本当のJVMクラス以上の言語糖であり、そのクラスは、Clojureのは、以来(参照しなければならないものです私たちはjavacを使ってコードをコンパイルしていません)。

私はdoto提案に同意しません。このビルダークラスは、1つのインスタンスを変更してそれを返すことによって、メソッドチェーンを実装するためにのみ機能します。 dotoは、インプレースの突然変異を必要とするJavaオブジェクトには最適ですが、クラスが親切であってもそれが不変であると思われる場合は、メソッドチェインのバージョン(つまり->)を使用してください。

3

(doto 
    (NutritionFacts.Builder. 240 8) 
    (.carbohydrates 27) 
    (.sodium 35) 
    (.calories 100) 
    (.build) 
) 

EDIT :
@Goran Jovicが指摘するように、これは最初のフォームで作成されたオブジェクトのすべてのメソッドを呼び出します。
Javaコードではメソッド連鎖が使用されるため、より一般的には適用されないため、この場合は機能します。

+0

唯一の理由です。 [doto](https://github.com/clojure/clojure/blob/f5f827ac9fbb87e770d25007472504403ed3d7a6/src/clj/clojure/core)に入れてください。clj#L3395)それは問題ありません! –

+0

@Goran Jovicあなたが提案したコードを変更しました。ありがとう! –

+0

うん、それだよ。 'doto'と' ..'の主な違いは、 'doto'は最初のフォームで定義された一つのオブジェクトのメソッドを呼び出し、' ..'は前のメソッドの結果を呼び出すことです。この場合、Javaメソッドは構築中のオブジェクトを返すので、同じです。 –

2

(.. (NutrionalFacts.Builder. 240 8) (calories 100) (sodium 35) (carbohydrates 27) (build))

8

使用..マクロ。それは2つの連続した点です。それはあなたが必要とするものだけを許可します - 前の結果で次のJavaメソッドを連続して呼び出すこと。

私は周りのREPLを持っていないが、あなたのラインのようなものに変換する必要があります。それは他の回答に簡潔に主張するのは難しいですが

(.. (NutritionFacts.Builder. 240 8) 
    (calories 100) 
    (sodium 350) 
    (carbohydrates 27) 
    (build)) 
0

このスレッドは数年前のことですが、スレッドファーストマクロは私が知る限り好ま​​しい方法ですが、$構文は必要ありません。 スラッシュ(/)は、同様に動作します:あなたは、いくつかの独立した形でVARを変異させるので、それは慣用的ではありません

(-> (Caffeine/newBuilder) 
     (.maximumSize 10000) 
     (.build)) 
+0

'(カフェイン/ newBuilder)は' '(NutritionalFacts $ Builderが。)'静的クラス(Javaの '新しいNutritionalFactsのコンストラクタへの呼び出しであるのに対し、静的メソッド(Javaの' Caffeine.newBuilder() ')の呼び出しです。ビルダー() '))、これは実際に受け入れられた答えと全く異なるものではありません。 – glts

+0

ああ、ok。私は構文のいくつかの更新があったと思った。ありがとう – Alex

関連する問題