Following the outline of our target DSL syntax, our first step is to create some type of order object that can then be configured:
- To do this, we'll start by creating an Order class to hold our order of pizza:
class Order(val id: String)
We've created this as a simple class with a single id property so that orders can be unique.
- Next, we'll create an Item class that can be added to an Order class:
abstract class Item(val name: String)
- Now, we'll add a map of Item and counts to our Order class:
class Order(val id: String) : Item("Order") {
val items: MutableMap<Item, Int> = mutableMapOf()
}
- With our Item map in place, we're ready to create an order. To do this, we'll create a top-level function:
fun order(init: Order.() -> Unit): Order {
val order = Order(UUID.randomUUID().toString())
order.init()
return order
}
The following two interesting elements should be observed in relation to this function:
- The function name mirrors the return type.
- We pass a function argument with an Order receiver.
These two characteristics allow us to call the function and understand that we are creating a new order, which helps enforce the declarative nature of the DSL. This also allows us to configure the Order instance within a passed lambda:
val order = order {
println(this.id)
}
Now, we're ready to start adding items to our order.