Everything else is just a tool to model your domain in a way that’s easier to read and reason about, and to produce much shorter code. Interfaces define module boundaries and can be mocked to enable simpler testing. Through classes, objects, and data structures, you can model your domain entities. Enums make a list of limited options crystal clear. Extensions allow you to add functionality to existing types, without having access to their original source code, giving advantage of better logic structure. With generics, you can write universal code, promoting reuse. And overloaded operators give that extra edge to common operations that benefit from succinct, crisp syntax.

Extensions

It is possible to extend functionality of existing types without resorting to inheritance. It is also possible to program standard, reusable functionality using delegation.

Extensions

Extensions can be defined for any class or interface, inside or outside of its module. They can add new methods or properties, but not stored properties. They are essentially functions with a default first parameter that maps to this.

Interfaces can have extensions:

interface Wrapped {
  fun unwrap(): Int
}

val Wrapped.value: Int
  get() = unwrap()

Classes can have extensions:

class Nut {
  companion object
}

fun Nut.Companion.crack(): String = "Yummy core"

fun Nut.crack(): String = Nut.crack()

fun Nut?.crack(): String {
  if (this == null) return "Nothing"
  return Nut.crack()
}

[--]