Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-line/complex property initializer without lambda

Tags:

lambda

kotlin

I want to initialize val property but property initializer is complex (contains several lines of code):

private val properties: Properties = {
    val properties = Properties()
    val stream = Application::class.java.getResourceAsStream("application.properties")
    properties.load(stream)
    properties
}.invoke()

Is it possible to re-write this property initializer without using lambda?

like image 528
Maxim Avatar asked Mar 08 '16 19:03

Maxim


2 Answers

You can use apply if your instance of the thing you are creating can be allocated at the start and then you want to modify it. Use let() when you have one thing, but want to turn it into another. You can use run() when you are starting with nothing, and building something to return.

Using apply:

private val properties = Properties().apply {
   load(Application::class.java.getResourceAsStream("application.properties")) 
}

or using let: (not the best example, but you get the point)

private val properties = Application::class.java.getResourceAsStream("application.properties")
    .let { stream -> 
              val props = Properties() 
              props.load(stream) 
              props
         }

or using run:

private val properties = run {
    val properties = Properties()
    val stream = Application::class.java.getResourceAsStream("application.properties")
    properties.load(stream)
    properties
}

Some libraries create variations of these and call them things like verifiedBy or initializedBy that basically do the same thing but make it clear the intent. Create new functions so your code reads the way you want, but also balance that with trying to use stdlib functions since that is consistent with other Kotlin users.

like image 193
Jayson Minard Avatar answered Nov 13 '22 13:11

Jayson Minard


There is apply extension function which is perfect for such use case. Using this function your code can be rewritten like:

private val properties = Properties().apply {
  load(Application::class.java.getResourceAsStream("application.properties"))
}
like image 7
Vladimir Mironov Avatar answered Nov 13 '22 14:11

Vladimir Mironov