* Multiple receivers are possible enabling extension methods like this:
class EnglishToGermanDictionary {
val translations = mapOf<String, String>(
"dog" to "Hund"
)
/* extension method for string in the context of dictionary */
val String.inGerman get() =
translations[this@String]
}
/* usage */
with (EnglishToGermanDictionary()) {
val word = "dog"
println("The translation of $word is ${word.inGerman}")
}
"cat".inGerman ---> compile error, method not found
* Built-in Singletons are also very convenient. Swap the word `class` for `object` and you get a singleton.
* The article left out lambdas. The function:
fun greet(name: String, day: String): String {
return "Hello $name, today is $day."
}
Can also be written as
val greet = {name, day -> "Hello $name, today is $day."}
* The compiler is really smart in infering types. Extension values don't need type-specification, e.g.:
val Double.km get() = this * 1000
* "when" in Kotlin doesn't need an argument, you can write arbitray rule-sets with it, with correctly inferred conditions:
val myVar = when {
stack.isEmpty() -> true
x == null -> false
currentIdx >= a && obj is MyType -> true /* here x has been inferred to be not null from the previous branch! */
else -> when {
user.isPresent() -> calculateSomething()
else -> throw IllegalStateException()
}
}
* sealed classes allow you to limit inheritance and get error when you miss something in a when
/* you actually don't have to nest the classes this way, but you can */
sealed class Expr {
sealed class IntExpr : Expr {
class Plus(val left: Int, val right: Int): IntExpr
class Minus(val left: Int, val right: Int): IntExpr
}
sealed class StringExpr : Expr {
class Substring(val str: String, val start: Int, val end: Int): StringExpr
}
}
/* Usage: */
val x: Expr
when (x) {
is Substring -> ...
is Plus -> x.left + x.right
/* compile error, we forgot to handle "Minus" from above */
}
The receivers mechanism is kind of nice; reminds me of this[0], except that in Kotlin, everything is still statically typed. It's a really clean way to implement Trygve Reenskaug's DCI architecture.
* Multiple receivers are possible enabling extension methods like this:
* Built-in Singletons are also very convenient. Swap the word `class` for `object` and you get a singleton.* The article left out lambdas. The function:
* The compiler is really smart in infering types. Extension values don't need type-specification, e.g.: * "when" in Kotlin doesn't need an argument, you can write arbitray rule-sets with it, with correctly inferred conditions: * sealed classes allow you to limit inheritance and get error when you miss something in a when