Menu
Coddy logo textTech

Приватные сеттеры

Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 9 из 57.

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

class Counter {
    var count = 0
        private set

    fun increment() {
        count++
    }
}

Внутри main:

val c = Counter()
c.increment()
println(c.count)
// c.count = 99   // ошибка: сеттер является приватным

Вывод:

1

Это подходит для значений, которые могут изменяться только по определённому правилу, например для счёта, который увеличивается только благодаря допустимым начислениям:

class Player(val name: String) {
    var score = 0
        private set
    private val _history = mutableListOf<Int>()
    val history: List<Int> get() = _history

    fun award(points: Int) {
        if (points <= 0) return
        score += points
        _history.add(points)
    }
}

Внутри main:

val p = Player("Ada")
p.award(10)
p.award(-5)
p.award(3)
println(p.score)
println(p.history)

Вывод:

13
[10, 3]

Приведённая выше history демонстрирует распространённый шаблон: приватный MutableList внутри класса, представленный наружу как доступный только для чтения List. Вызывающий код может читать элементы, но у него нет add или remove, чтобы изменять их:

private val _items = mutableListOf<String>()
val items: List<String> get() = _items      // представление только для чтения
// снаружи: items.add("x")                  // ошибка: у List нет add

val никогда не изменяется после создания, даже внутри класса. var с private set остаётся изменяемым только внутри класса. Выбирай val для значений, которые не меняются на протяжении всей жизни объекта:

class Order(val id: Int) {            // никогда не изменяется
    var status = "new"
        private set                       // изменяется, но только внутри Order
    fun ship() { status = "shipped" }
}
challenge icon

Задание

Легко

Завершите класс Elevator(val topFloor: Int). floor и trips можно читать извне, но изменять их можно только внутри класса (private set). goTo(target) перемещает между этажом 0 и topFloor: допустимое перемещение на другой этаж обновляет floor, добавляет 1 к trips и возвращает true; недопустимое перемещение или перемещение на тот же этаж возвращает false.

Предоставленный код считывает верхний этаж, а затем целевые этажи. После перемещения он выводит floor 3, а если перемещение было отклонено — stay 3, и наконец выводит trips: с количеством поездок.

Ваш код должен находиться в Elevator.kt. В Main.kt находится предоставленный код ввода/вывода, и его нельзя изменять.

Попробуйте сами

fun main() {
    // Предоставленный код ввода/вывода: оставьте его как есть
    val input = generateSequence(::readLine).toList()
    val lift = Elevator(input[0].toInt())
    for (line in input.drop(1)) {
        val moved = lift.goTo(line.toInt())
        println("${if (moved) "floor" else "stay"} ${lift.floor}")
    }
    println("trips: ${lift.trips}")
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Kotlin