Skip to content

Instantly share code, notes, and snippets.

Last active May 9, 2020
What would you like to do?
Type safe builder pattern in Kotlin using Phantom Types (inspired by
import Thing.*
fun main() {
val foo0: Thing = Thing.setB(2).setA(1).setC(3).setD(4).build()
println("foo0: $foo0")
val foo1: Thing = Thing.setA(1).setB(2).setC(3).setD(4).build()
println("foo1: $foo1")
val foo2: Thing = Thing.setC(3).setB(2).setA(1).setD(4).build()
println("foo2: $foo2")
// val foo3: Thing = Thing.setA(1).setB(2).setC(3).build() // Compile error
class Thing constructor(
private val a: Int,
private val b: Int,
private val c: Int,
private val d: Int
) {
abstract class OK
abstract class NO
companion object : ThingBuilder<NO, NO, NO, NO>()
override fun toString() = "a = $a, b = $b, c = $c, d = $d"
open class ThingBuilder<A, B, C, D> internal constructor(
internal var a: Int = 0,
internal var b: Int = 0,
internal var c: Int = 0,
internal var d: Int = 0
) {
fun setA(a: Int): ThingBuilder<OK, B, C, D> = ThingBuilder(a, b, c, d)
fun setB(b: Int): ThingBuilder<A, OK, C, D> = ThingBuilder(a, b, c, d)
fun setC(c: Int): ThingBuilder<A, B, OK, D> = ThingBuilder(a, b, c, d)
fun setD(d: Int): ThingBuilder<A, B, C, OK> = ThingBuilder(a, b, c, d)
fun ThingBuilder<OK, OK, OK, OK>.build() = Thing(a, b, c, d)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment