0Pricing
Kotlin Academy · Урок

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

Получайте доступ к внешней области видимости

«Внутренние классы» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Ключевое слово inner

Пометка вложенного класса как inner добавляет ему ссылку на внешний экземпляр, поэтому он может обращаться к членам внешнего класса.

class Outer {
    val msg = "Hello"
    inner class Inner {
        fun show() = msg
    }
}

fun main() {
    println(Outer().Inner().show())
}

Создание экземпляра inner-класса

Поскольку inner-классу нужен внешний экземпляр, его создают на основе такого экземпляра: Outer().Inner().

class Engine {
    val power = 100
    inner class Turbo {
        fun boosted() = power * 2
    }
}

fun main() {
    println(Engine().Turbo().boosted())
}

Доступ к свойствам внешнего класса

Inner-класс напрямую читает и использует свойства внешнего класса, как если бы они были его собственными.

class Counter {
    var count = 0
    inner class Stepper {
        fun step() { count++ }
    }
}

fun main() {
    val c = Counter()
    c.Stepper().step()
    println(c.count)
}

Вызов методов внешнего класса

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

class Printer {
    fun line(s: String) = println(s)
    inner class Job {
        fun run() = line("printing")
    }
}

fun main() {
    Printer().Job().run()
}

Синтаксис this@Outer

Чтобы явно обратиться к внешнему экземпляру, например при совпадении имён, используйте this@Outer.

class Outer {
    val value = 10
    inner class Inner {
        val value = 20
        fun outerValue() = this@Outer.value
    }
}

fun main() {
    println(Outer().Inner().outerValue())
}

Зачем нужен inner

Используйте inner, когда вложенному типу действительно нужно взаимодействовать с конкретным внешним экземпляром и совместно использовать его состояние.

class Wallet {
    var balance = 50
    inner class Transaction(val amount: Int) {
        fun apply() { balance += amount }
    }
}

fun main() {
    val w = Wallet()
    w.Transaction(25).apply()
    println(w.balance)
}

Каждый inner-класс связан с одним внешним экземпляром

Экземпляр inner-класса связан именно с тем внешним экземпляром, который его создал; изменения передаются этому объекту.

class Box(var size: Int) {
    inner class Resizer {
        fun grow() { size += 1 }
    }
}

fun main() {
    val b = Box(3)
    b.Resizer().grow()
    println(b.size)
}

Inner-класс и вложенный класс

Без inner вложенный класс изолирован. С inner он захватывает внешний экземпляр. Всё различие заключается в этом ключевом слове.

class Outer {
    val tag = "X"
    inner class A { fun get() = tag }
}

fun main() {
    println(Outer().A().get())
}

Замечание о памяти

Поскольку экземпляр inner-класса сохраняет внешний экземпляр доступным, будьте внимательны с долгоживущими объектами inner-класса, чтобы случайно не удерживать внешний объект.

class Service {
    val id = 1
    inner class Worker { fun who() = id }
}

fun main() {
    println(Service().Worker().who())
}

Практический итератор

Inner-класс отлично подходит для итератора, который обходит состояние объемлющей его коллекции.

class Stack {
    private val items = mutableListOf(1, 2, 3)
    inner class Reader {
        fun all() = items.joinToString()
    }
}

fun main() {
    println(Stack().Reader().all())
}

Объединение понятий

Inner-классы могут использовать состояние внешнего класса и устранять неоднозначность с помощью this@Outer.

class Outer {
    val n = 5
    inner class Inner {
        fun doubled() = this@Outer.n * 2
    }
}

fun main() {
    println(Outer().Inner().doubled())
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли inner-классы.

Итоги

Вы узнали об inner-классах:

  • inner предоставляет доступ к внешнему экземпляру и его членам.
  • Их создают через внешний экземпляр: Outer().Inner().
  • Используйте this@Outer, чтобы обратиться к объемлющему экземпляру.
  • Экземпляры inner-классов сохраняют внешний экземпляр доступным.
class Outer {
    val v = 1
    inner class Inner { fun get() = v }
}

fun main() {
    println(Outer().Inner().get())
}

Часто задаваемые вопросы

Урок «Внутренние классы» бесплатный?

Да — полный текст урока «Внутренние классы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Внутренние классы»?

Получайте доступ к внешней области видимости Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Внутренние классы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Вложенные классы
  2. Внутренние классы
  3. Анонимные объекты
  4. Локальные классы
← Назад к Kotlin Academy