Kotlin supports nesting classes within other classes. A nested class is declared directly enside another class and does not hold a reference to a instance of the outer class:
class Outer {
private val value = 1
class Nested {
fun getValue() = 2
}
}
val result = Outer.Nested().getValue() // Returns 2
When a nested class is marked with the inner keyword, it gains access to members of the outer class instance because it implicitly holds a reference to that instance:
class Outer {
private val value = 1
inner class Inner {
fun getValue() = value
}
}
val result = Outer().Inner().getValue() // Returns 1
Anonymous inner classes are created using object expressions, commonly used for implementing callback interfaces:
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { /* ... */ }
override fun mouseEntered(e: MouseEvent) { /* ... */ }
})
On the JVM, if the target is a functional Java interface (SAM interface), a lambda can be used instead:
val listener = ActionListener { println("clicked") }
Enum classes in Kotlin provide type-safe enumeration values:
enum class Direction { NORTH, SOUTH, WEST, EAST }
Each enum constant is an instance of the enum class and can be initialized with parameters:
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}
Enum constants may also override abstract methods by providing anonymous class implementations:
enum class ProtocolState {
WAITING {
override fun transition() = TALKING
},
TALKING {
override fun transition() = WAITING
};
abstract fun transition(): ProtocolState
}
If an enum class defines any members beyond its constants, a semicolon must separate the constant list from the member declarations.
Enum classes can implement interfaces, either providing a shared implementation or individual overrides per constant:
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
PLUS {
override fun apply(a: Int, b: Int): Int = a + b
},
TIMES {
override fun apply(a: Int, b: Int): Int = a * b
};
override fun applyAsInt(a: Int, b: Int) = apply(a, b)
}
Kotlin provides built-in functions to work with enum constants. The values() function returns an array of all constants, and valueOf(name) retrieves a constant by its name:
Direction.valueOf("NORTH") // Returns Direction.NORTH
Direction.values() // Returns [NORTH, SOUTH, WEST, EAST]
Generic helper functions enumValues<T>() and enumValueOf<T>() (available since Kotlin 1.1) allow working with enums in a reified generic context:
inline fun <reified T : Enum<T>> printNames() {
println(enumValues<T>().joinToString { it.name })
}
printNames<RGB>() // Outputs: RED, GREEN, BLUE
Each enum constant exposes name (its declaration name as a String) and ordinal (its zero-based position in the declaration order). Enum classes also implement Comparable, with comparison based on declaration order.