Introduction of Function Literals
-
Function literals are frequently used as a constructor of objects.
-
Well known examples are
build.gradle.kts
andjetpack-compose
for Andriod or Desktop UIs.
In the sequel let's consider the following builder function, a function literal takes the form
fun builder(dummyName: ClassA.() -> Unit) { ... }
which means that:
- We define a lambda function that can be treated as a method of
ClassA
- This lambda function takes the signature
() -> Unit
. - To call this lambda function, we invoke
classA.dummyName()
. builder
orchestrates the execution of the above defined operations.
Example
class Properties { var time: String? = null } class BuildInfo { private var properties: Properties? = null fun withProperties(configure: Properties.() -> Unit) { val _properties = Properties() _properties.configure() properties = _properties } } class SpringBootExtension { private var buildInfo: BuildInfo? = null fun withBuildInfo(configure: BuildInfo.() -> Unit) { val _buildInfo = BuildInfo() _buildInfo.configure() this.buildInfo = _buildInfo } }
Let's create a builder function which builds a SpringBootExtension
object.
// builder function fun springBootEextension(build: SpringBootExtension.() -> Unit): SpringBootExtension { val extension = SpringBootExtension() extension.build() return extension }
Which means that
springBootEextension
accepts a lambda function which is defined as if we are inside of the class definition ofSpringBootExtension
,- The name
build
is in fact dummy and can be anything we want, it is just a name to invoke the execution of the lambda.
fun createExtension() { val extension = springBootEextension { // trailing closure without input params withBuildInfo { // it is a method inside of SpringBootEextension // it is accessible by the closure because our context is now SpringBootEextension withProperties { // accepts another closure for configuration time = null // context is now Property class, can make changes to the created Property object } } } }
-
In short,
ClassA.() -> Unit
can be read as configuration ofClassA
in many cases (and bear in mind that it is a lambda function defined inside ofClassA
). -
In terms of this terminology:
springBootEextension(_: SpringBootExtension.() -> Unit)
accepts a configuration ofSpringBootExtension
withBuildInfo(_: BuildInfo.() -> Unit)
accepts a configuration ofBuildInfo
withProperties(_: Properties.() -> Unit)
accepts a configuration ofProperties