用于Scala和Java的类型安全的Builder库

ept*_*ptx 4 java scala scala-java-interop

下面是Scala中类型安全,流畅的构建器模式,如http://www.tikalk.com/java/blog/type-safe-builder-scala-using-type-constraints中所述.它与Scala和Java的Builder Library类似,但特别涉及编译时构建器检查.这怎么能从Java调用?可以使用干净的Scala Java API来实现"scala.Predef $$ eq $ colon $ eq"参数吗?

sealed trait TBoolean
sealed trait TTrue extends TBoolean
sealed trait TFalse extends TBoolean

class Builder[HasProperty <: TBoolean] private(i: Int) {
  protected def this() = this(-1)
  def withProperty(i: Int)(implicit ev: HasProperty =:= TFalse) = new Builder[TTrue](i)
  def build(implicit ev: HasProperty =:= TTrue) = println(i)
}

//javap output
    public class Builder extends java.lang.Object implements scala.ScalaObject{
    public Builder withProperty(int, scala.Predef$$eq$colon$eq); //How is this called from Java?
    public void build(scala.Predef$$eq$colon$eq);
    public Builder();
}
object Builder {
  def apply() = new Builder[TFalse]
}
Run Code Online (Sandbox Code Playgroud)

Aar*_*rup 6

您应该能够使用Java中的这个API,与Scala版本相比会产生一些额外的噪音.一些便利领域会让事情变得安静:

object Builder {
   def apply() = new Builder[TFalse]
   val unassigned = =:=.tpEquals[TFalse]
   val assigned = =:=.tpEquals[TTrue] 
}
Run Code Online (Sandbox Code Playgroud)

Java客户端代码应该看起来像

Builder$.MODULE$.apply()
   .withProperty(10, Builder$.MODULE$.unassigned())
   .build(Builder$.MODULE$.assigned());
Run Code Online (Sandbox Code Playgroud)

build方法必须检查是否已分配每个属性,因此在推广到多个属性时会产生相当大的噪音:

Builder$.MODULE$.apply()
   .withProp1(10, Builder$.MODULE$.unassigned())
   .withProp2(20, Builder$.MODULE$.unassigned())
   .withProp3(30, Builder$.MODULE$.unassigned())
   // ...
   .build(Builder$.MODULE$.assigned(), 
          Builder$.MODULE$.assigned(), 
          Builder$.MODULE$.assigned(), 
          //...
         );
Run Code Online (Sandbox Code Playgroud)

对于辅助类中的一些静态委托(以及一些静态导入),您应该能够将其归结为:

createBuilder()
   .withProp1(10, unassigned())
   .withProp2(20, unassigned())
   .build(assigned(), assigned());
Run Code Online (Sandbox Code Playgroud)