Open In App

Idioms in Kotlin

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:



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)

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 delegating 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
{
  // or a different type of table if desired
  constructor() : this(TreeBasedTable.create()) 
}

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) 
}

This will print “foo” and will return Unit.




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 applying 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 a 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
}


Article Tags :