Kotlin

Idioms

Creating DTOs (POJOs/POCOs)

Data classes in kotlin are classes created to do nothing but hold data. Such classes are marked as data:

data class User(var firstname: String, var lastname: String, var age: Int)

The code above creates a User class with the following automatically generated:

  • Getters and Setters for all properties (getters only for vals)
  • equals()
  • hashcode()
  • toString()
  • copy()
  • componentN() (where N is the corresponding property in order of declaration)

Just as with a function, default values can also be specified:

data class User(var firstname: String = "Joe", var lastname: String = "Bloggs", var age: Int = 20)

More details can be found here Data Classes.

Filtering a list

val list = listOf(1,2,3,4,5,6)

//filter out even numbers

val even = list.filter { it % 2 == 0 }

println(even) //returns [2,4]

Delegate to a class without providing it in the public constructor

Assume you want to delegate to a class but you do not want to provide the delegated-to class in the constructor parameter. Instead, you want to construct it privately, making the constructor caller unaware of it. At first this might seem impossible because class delegation allows to delegate only to constructor parameters. However, there is a way to do it, as given in this answer:

class MyTable private constructor(table: Table<Int, Int, Int>) : Table<Int, Int, Int> by table {

    constructor() : this(TreeBasedTable.create()) // or a different type of table if desired

}

With this, you can just call the constructor of MyTable like that: MyTable(). The Table<Int, Int, Int> to which MyTable delegates will be created privately. Constructor caller knows nothing about it.

This example is based on this SO question.

Serializable and serialVersionUid in Kotlin

To create the serialVersionUID for a class in Kotlin you have a few options all involving adding a member to the companion object of the class.

The most concise bytecode comes from a private const val which will become a private static variable on the containing class, in this case MySpecialCase:

class MySpecialCase : Serializable {
    companion object {
        private const val serialVersionUID: Long = 123
    }
}

You can also use these forms, each with a side effect of having getter/setter methods which are not necessary for serialization…

class MySpecialCase : Serializable {
    companion object {
        private val serialVersionUID: Long = 123
    }
}

This creates the static field but also creates a getter as well getSerialVersionUID on the companion object which is unnecessary.

class MySpecialCase : Serializable {
    companion object {
        @JvmStatic private val serialVersionUID: Long = 123
    }
}  

This creates the static field but also creates a static getter as well getSerialVersionUID on the containing class MySpecialCase which is unnecessary.

But all work as a method of adding the serialVersionUID to a Serializable class.

Fluent methods in Kotlin

Fluent methods in Kotlin can be the same as Java:

fun doSomething() {
   someOtherAction()
   return this
}

But you can also make them more functional by creating an extension function such as:

fun <T: Any> T.fluently(func: ()->Unit): T {
    func()
    return this
}

Which then allows more obviously fluent functions:

fun doSomething() {
   return fluently { someOtherAction() }
}

Use let or also to simplify working with nullable objects

let in Kotlin creates a local binding from the object it was called upon. Example:

val str = "foo"
str.let {
    println(it) // it
}  

This will print "foo" and will return Unit.

The difference between let and also is that you can return any value from a let block. also in the other hand will always reutrn Unit.

Now why this is useful, you ask? Because if you call a method which can return null and you want to run some code only when that return value is not null you can use let or also like this:

val str: String? = someFun()
str?.let {
    println(it)
}

This piece of code will only run the let block when str is not null. Note the null safety operator (?).

Use apply to initialize objects or to achieve method chaining

The documentation of apply says the following:

calls the specified function block with this value as its receiver and returns this value.

While the kdoc is not so helpful apply is indeed an useful function. In layman’s terms apply establishes a scope in which this is bound to the object you called apply on. This enables you to spare some code when you need to call multiple methods on an object which you will then return later. Example:

File(dir).apply { mkdirs() }

This is the same as writing this:

fun makeDir(String path): File {
    val result = new File(path)
    result.mkdirs()
    return result
}

This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow