Skip to content

Instantly share code, notes, and snippets.

@jserranohidalgo
Created June 25, 2015 18:45
Show Gist options
  • Save jserranohidalgo/dbd5eef6991cd314c5ce to your computer and use it in GitHub Desktop.
Save jserranohidalgo/dbd5eef6991cd314c5ce to your computer and use it in GitHub Desktop.
Typesafe builders
package object typesafe_builder{
import scala.language.higherKinds
// Auxiliary type constructor. It allows us to represent
// that an argument has been set.
type Id[T] = T
// The target domain class
case class Person(age: Int, name: String)
// The builder, with a private constructor. It can only
// be initialised through the companion object.
class PersonBuilder[AgeF[_], NameF[_]] private(
val age: AgeF[Int],
val name: NameF[String]
){
def withAge(age: Int) =
new PersonBuilder[Id,NameF](age, name)
def withName(name: String) =
new PersonBuilder[AgeF,Id](age, name)
}
object PersonBuilder{
def apply(): PersonBuilder[Any, Any] =
new PersonBuilder(None, None)
}
// The builder is typesafe, i.e. the compiler won't let us build
// an object unless we specify *all* the arguments.
implicit class ToPerson(builder: PersonBuilder[Id,Id]){
def toPerson = Person(builder.age, builder.name)
}
// Won't compile!
// PersonBuilder().toPerson
// PersonBuilder().withName("pepe").toPerson
// PersonBuilder().withAge(10).toPerson
// Compiles!
assert( PersonBuilder().withName("pepe").withAge(10).toPerson == Person(10,"pepe") )
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment