Below is a type-safe, fluid, builder pattern in Scala as described at http://www.tikalk.com/java/blog/type-safe-builder-scala-using-type-constraints. It's similar to Builder Library for Scala and Java, but deals specifically with compile-time builder checks. How can this called from Java? Can it be done with a clean API for Scala AND Java given the "scala.Predef$$eq$colon$eq" parameters?
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]
}
You should be able to use this API from Java, with some extra noise compared to the Scala version. A few convenience fields will quiet things a bit:
The Java client code should end up looking like
The
build
method has to check that every property is assigned, so it gets pretty noisy when you generalize to multiple properties:With some static delegates in a helper class (and some static imports), you should be able to get this down to something like:
OK, thanks to Aaron and ittayd...here is a builder with a fluid API for Scala and Java:
Scala Usage (Type Safe):
Java Usage I (type safe, but ugly):
Java Usage II (not type safe, but much cleaner, using @Bridge calls):