Menu
CoddyTech

私有设置器

本课属于 Coddy Kotlin 学习旅程的“面向对象编程”单元。第 9 课,共 57 课。

通常,代码外部应当可以读取属性,但不能修改属性。private set会保留公开的 getter,并将 setter 设为私有:

class Counter {
    var count = 0
        private set

    fun increment() {
        count++
    }
}

在 main 内部:

val c = Counter()
c.increment()
println(c.count)
// c.count = 99   // 错误:setter 是私有的

输出:

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 创建后永远不会改变,即使在类内部也不会。使用 private set 的 var 只会在类内部保持可变。对于在对象整个生命周期内都固定不变的值,选择 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,将 trips 加 1,并返回 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 在线编辑器