Suppose I have Person
and House
classes :
data class Person(val name: String, val age: Int)
data class House(val address: String, val persons: List<Person>?)
I want to build a DSL for it . This is what I’ve done :
data class Person(val name: String, val age: Int)
class Persons : ArrayList<Person>() {
fun person(p : Person) {
add(p)
}
}
data class House(val address: String, val persons: List<Person>?) {
class Builder {
var address = ""
private val persons = mutableListOf<Person>()
fun persons(block : Persons.() -> Unit) {
persons.addAll(Persons().apply(block))
}
fun addList(vararg list : Person) {
persons.addAll(list)
}
fun build() = House(address , persons.takeIf { it.isNotEmpty() })
}
}
private fun house(block: House.Builder.() -> Unit) = House.Builder().apply(block).build()
@Test
fun testPersons() {
val house = house {
address = "Broadway 1"
persons {
person(Person("John" , 21))
person(Person("Amy" , 20))
}
}
println(house)
}
@Test
fun testList() {
val house = house {
address = "Broadway 1"
addList(Person("John" , 21) , Person("Amy" , 20))
}
println(house)
}
The two tests both outputs
House(address=Broadway 1, persons=[Person(name=John, age=21), Person(name=Amy, age=20)])
House(address=Broadway 1, persons=[Person(name=John, age=21), Person(name=Amy, age=20)])
But these are not what I want .
The problem is in House.Builder’s persons() and addList() function.
They cannot achieve what I really want to do :
@Test // this is what I really want
fun test() {
val house = house {
address = "Broadway 1"
persons {
Person("John" , 21)
Person("Amy" , 20)
}
}
println(house) // House(address=Broadway 1, persons=null)
}
How to achieve such DSL ?
Thanks.