如何在Clojure中使用构建器模式创建类似Java的对象?

Rob*_*ler 13 clojure

使用Clojure,如何创建以下对象?该对象取自java代码(From Effective Java):

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

ama*_*loy 23

虽然很难与其他答案1中的简洁争论,..但有些失宠,取而代之的是更多才多艺->.我个人更喜欢:

(-> (NutritionFacts$Builder. 240 8) 
    (.calories 100)
    (.sodium 350)  
    (.carbohydrates 27) 
    (.build))
Run Code Online (Sandbox Code Playgroud)

这是几个角色,但你获得了两件事:

  • 明晰.我可以查看钠线(例如)并告诉它是一个Java方法调用,因为它就在.那里.
  • 灵活性.如果我需要,我可以在中间链接一些非方法调用(将其打印到stdout,比方说),或者在所有这些调用结束时将其输入到其他函数调用中.

最重要的是,这个问题的每个其他答案都会使类名错误:Java的NutritionFacts.Builder是名为NutritionFacts $ Builder的真正JVM类的语言糖,而该类是Clojure必须引用的类(因为我们没有使用javac来编译我们的代码).

1我不同意这个doto建议:它的作用只是因为这个Builder类碰巧通过改变单个实例然后返回它来实现它的方法链接.doto对于需要就地变异的Java对象来说非常棒,但是当一个类足够假装它是不可变的时,你应该真的使用方法链接版本(即->).


Gor*_*vic 8

使用..宏.这是两个连续的点.它允许你需要的东西 - 连续调用前一个结果的下一个Java方法.

我没有REPL,但你的行应该转换为:

(.. (NutritionFacts.Builder. 240 8) 
    (calories 100)
    (sodium 350)  
    (carbohydrates 27) 
    (build))
Run Code Online (Sandbox Code Playgroud)