Menu
CoddyTech

复习:订单追踪器

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

challenge icon

挑战

中等

用本章的特殊类来跟踪订单。

  • 枚举 Status 包含常量 NEW、PAID、SHIPPED、DELIVERED 和 CANCELLED,每个常量都有一个 label(new、paid 等),以及 canMoveTo(next):新订单可以变为已付款或已取消,已付款订单可以变为已发货或已取消,已发货订单可以变为已送达,其他状态转换均不允许。
  • Order(id, item, status) 是一个数据类,其状态初始为 NEW。
  • 密封接口 Outcome 有两种情况:Updated(order) 和 Rejected(id, reason)。
  • Tracker.place(item) 会使用下一个 id(1、2……)创建订单并返回该订单。move(id, target) 会返回 Rejected,并附带 no such order 或 cannot go from new to delivered,也可能保存更改后的订单副本并返回 Updated。summary() 按枚举中的顺序返回每种状态的订单数量,并省略数量为 0 的状态:paid 1, cancelled 1,或者 no orders。
  • describe(outcome) 使用穷尽式 when,并返回已更新订单的文本,或 rejected 2: no such order。

提供的代码会读取 place tea 或 <status> <id> 这样的命令,例如 paid 1,打印每个已创建的订单、每个描述后的结果,最后打印摘要。

你的代码要写在 Status.kt、Order.kt、Outcome.kt、Updated.kt、Rejected.kt、Tracker.kt 和 Functions.kt 中。Main.kt 包含提供的输入/输出代码,不能编辑。

亲手试试

fun main() {
    // 已提供的输入/输出代码:保持原样。
    val input = generateSequence(::readLine).toList()
    val tracker = Tracker()
    for (cmd in input) {
        val p = cmd.split(" ")
        if (p[0] == "place") {
            println(tracker.place(p[1]))
        } else {
            val target = Status.entries.find { it.label == p[0] }
            if (target == null) println("unknown status ${p[0]}")
            else println(describe(tracker.move(p[1].toInt(), target)))
        }
    }
    println(tracker.summary())
}

面向对象编程中的所有课

自己练习: Kotlin 在线编辑器