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.

Enums

Custom types that represent a fixed set of discreet values, a.k.a. enumerations.

Enums

Simple enum:

enum class Direction {
  NORTH, SOUTH, WEST, EAST
}

val north = Direction.valueOf("NORTH")
val allDirections = Direction.values()
val alsoAllDirections = Direction.entries
val southInstruction = "Go ${Direction.SOUTH.name}." +
  " It has index ${Direction.SOUTH.ordinal} in the enum."
val south = Direction.entries[Direction.SOUTH.ordinal]

An enum class can have properties and methods. Enum values can have parameters, but they cannot be created outside of their enum class. For example, val white = Color(0xFFFFFF) is not possible in the example below.

enum class Color(val rgb: Int) {
  RED(0xFF0000),
  GREEN(0x00FF00),
  BLUE(0x0000FF);

  fun poeticName() = when (this) {
    RED -> "crimson"
    GREEN -> "emerald"
    BLUE -> "azure"
  }
}

Enums can implement interfaces, but cannot derive from a class. Enum values can customize common members, as well as define new ones, specific to that value.

interface Rateable {
  val rating: Double
}

enum class Sentiment(override val rating: Double): Rateable {
  HAPPY(1.0),
  SAD(-1.0),
  NEUTRAL(0.0)
}

enum class Reaction(val emoji: String): Rateable {
  LOVE("❤️") {
    override val sentiment
      get() = Sentiment.HAPPY

    override val rating: Double
      get() = super.rating * 2
  },

  LIKE("👍") {
    override val sentiment
      get() = Sentiment.HAPPY
  },

  DISLIKE("👎") {
    override val sentiment
      get() = Sentiment.SAD
  },

  SURPRISE("😮") {
    override val sentiment
      get() = Sentiment.NEUTRAL
  };

  abstract val sentiment: Sentiment

  override val rating: Double
    get() = sentiment.rating
}

[--]