以下是Scala中类型安全,流畅的构建器模式,如http://www.tikalk.com/java/blog/type-safe-builder-scala-using-type-constraints所述。它与Builder Library for Scala and Java类似,但专门处理编译时构建器检查。这怎么能从Java调用?在给出“scala.Predef $$ eq $ colon $ eq”参数的情况下,是否可以使用干净的Scala AND Java API?
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]
}
答案 0 :(得分:6)
您应该能够使用Java中的这个API,与Scala版本相比会产生一些额外的噪音。一些便利领域会让事情变得安静:
object Builder {
def apply() = new Builder[TFalse]
val unassigned = =:=.tpEquals[TFalse]
val assigned = =:=.tpEquals[TTrue]
}
Java客户端代码应该看起来像
Builder$.MODULE$.apply()
.withProperty(10, Builder$.MODULE$.unassigned())
.build(Builder$.MODULE$.assigned());
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(),
//...
);
在帮助程序类(以及一些静态导入)中有一些静态委托,你应该可以将其归结为:
createBuilder()
.withProp1(10, unassigned())
.withProp2(20, unassigned())
.build(assigned(), assigned());
答案 1 :(得分:3)
好的,感谢Aaron和ittayd ......这是一个为Scala和Java提供流畅API的构建器:
import annotation.bridge
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):Int = i
@bridge def withProperty(i: Int) = new Builder[TTrue](i)
@bridge def build = build(null)
}
object Builder {
def apply() = new Builder[TFalse]
val unassigned = =:=.tpEquals[TFalse]
val assigned = =:=.tpEquals[TTrue]
}
Scala用法(类型安全):
val v = Builder().withProperty(2).build
Java Usage I(类型安全但丑陋):
int i = Builder$.MODULE$.apply()
.withProperty(5, Builder$.MODULE$.unassigned())
.build(Builder$.MODULE$.assigned());
Java Usage II(不是类型安全,但更干净,使用@Bridge调用):
static Builder createBuilder() {
return Builder$.MODULE$.apply();
}
...
int j = createBuilder().withProperty(7).build();