Menu
CoddyTech

次构造函数

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

类可以通过次构造函数提供额外的创建方式,次构造函数使用 constructor 声明。每个次构造函数都必须使用 this(...) 调用主构造函数:

class Temperature(val celsius: Double) {
    constructor(fahrenheit: Int) : this((fahrenheit - 32) * 5 / 9.0)
}

在 main 中:

println(Temperature(20.0).celsius)
println(Temperature(212).celsius)

输出:

20.0
100.0

默认参数通常可以避免使用次构造函数。优先使用一个带默认值的主构造函数;当输入形式不同时,例如需要解析文本时,再使用次构造函数:

class Color(val r: Int, val g: Int, val b: Int) {
    constructor(gray: Int) : this(gray, gray, gray)
    constructor(hex: String) : this(hex.substring(0, 2).toInt(16), hex.substring(2, 4).toInt(16), hex.substring(4, 6).toInt(16))

    fun label() = "rgb($r, $g, $b)"
}

在 main 中:

println(Color(128).label())
println(Color("FF8000").label())

输出:

rgb(128, 128, 128)
rgb(255, 128, 0)

主构造函数及其 init 代码块会先运行,然后运行次构造函数的函数体:

class Log(val name: String) {
    init { println("primary: $name") }
    constructor(id: Int) : this("log-$id") {
        println("secondary: $id")
    }
}

在 main 中:

Log(7)

输出:

primary: log-7
secondary: 7

每个重载都必须能明确匹配构造函数。不能有两个参数类型相同的构造函数,而且无法明确匹配到某个构造函数的调用会导致编译失败。

class Size(val w: Int, val h: Int) {
    constructor(side: Int) : this(side, side)   // Size(3) -> 一个正方形
    // constructor(w: Int) : this(w, 1)        // 错误:与上面的签名相同
}
challenge icon

挑战

简单

请补全类 Duration(val seconds: Int),添加一个次构造函数 (minutes: Int, seconds: Int),以及另一个接收文本的构造函数,例如 1:30 或 2:05:10(小时:分钟:秒)。添加 format(),使其返回格式为 h:mm:ss 的字符串,其中分钟和秒都用两位数字表示。

提供的代码会读取包含一个或两个冒号的文本时长,使用文本构造函数创建每个时长并打印 format(),然后打印 total 和格式化后的总时长。

请将代码写在 Duration.kt 中。Main.kt 包含提供的输入/输出代码,不能编辑。

亲手试试

fun main() {
    // 提供的输入输出代码:保持原样。
    val input = generateSequence(::readLine).toList()
    var total = 0
    for (line in input) {
        val d = Duration(line)
        println(d.format())
        total += d.seconds
    }
    println("total " + Duration(total).format())
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Kotlin 在线编辑器