Вложенные классы

Классы могут быть вложены в другие классы

class Outer {
    private val bar: Int = 1
    class Nested {
        fun foo() = 2
    }
}

val demo = Outer.Nested().foo() // == 2

Внутренние классы

Класс может быть отмечен как внутренний с помощью слова inner, тем самым он будет иметь доступ к членам внешнего класса. Внутренние классы содержат ссылку на объект внешнего класса:

class Outer {
    private val bar: Int = 1
    inner class Inner {
        fun foo() = bar
    }
}

val demo = Outer().Inner().foo() // == 1

Подробнее об использовании this во внутренних классах: Qualified this expressions

Анонимные внутренние классы

Анонимные внутренние экземпляры классов создаются с помощью object expression:

window.addMouseListener(object: MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
        // ...
    }
                                                                                                            
    override fun mouseEntered(e: MouseEvent) {
        // ...
    }
})

Если объект является экземпляром функционального Java-интерфейса (т.е. Java-интерфейса с единственным абстрактным методом), вы можете создать его с помощью лямбда-выражения с префиксом — типом интерфейса:

val listener = ActionListener { println("clicked") }