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

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

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

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

Вы также можете использовать интерфейсы с вложенностью. Возможны любые комбинации классов и интерфейсов: вы можете вкладывать интерфейсы в классы, классы в интерфейсы и интерфейсы в интерфейсы.

interface OuterInterface {
    class InnerClass
    interface InnerInterface
}

class OuterClass {
    class InnerClass
    interface InnerInterface
}

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

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

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

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

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

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

Экземпляры анонимного внутреннего класса создаются с помощью объектов-выражений.

window.addMouseListener(object : MouseAdapter() {

    override fun mouseClicked(e: MouseEvent) { ... }

    override fun mouseEntered(e: MouseEvent) { ... }
})

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

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