Menu
CoddyTech

默认方法

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

接口方法可以有方法体。每个没有重写它的类都会使用这个默认实现:

interface Greeter {
    val name: String
    fun greet() = "Hello, I am $name"
}
class Robot(override val name: String) : Greeter
class Pirate(override val name: String) : Greeter {
    override fun greet() = "Ahoy! $name here"
}

在 main 中:

println(Robot("R2").greet())
println(Pirate("Anne").greet())

输出:

Hello, I am R2
Ahoy! Anne here

默认方法是根据接口的其他成员编写的。类只需提供不同的少数几个成员,就能获得其余成员:

interface Priced {
    val cents: Int
    fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
    fun isAffordable(budget: Int) = cents <= budget
}
class Coffee : Priced {
    override val cents = 450
}

在 main 中:

val c = Coffee()
println(c.formatted())
println(c.isAffordable(400))

输出:

$4.50
false

属性可以有默认 getter,但接口没有支持字段,因此无法存储值。带有初始化器的属性无法编译,而通过 getter 计算值则可以:

interface Box {
    val width: Int
    val height: Int
    val area: Int
        get() = width * height
    // val count = 0      // 错误:接口中不允许使用属性初始化表达式
}
class Tile(override val width: Int, override val height: Int) : Box

在 main 中:

println(Tile(3, 4).area)

输出:

12

重写仍然可以使用默认实现。在类中,super.method() 会调用接口中的版本:

interface Priced {
    val cents: Int
    fun formatted() = "$%d.%02d".format(cents / 100, cents % 100)
}
class Coffee : Priced {
    override val cents = 450
    override fun formatted() = "coffee " + super.formatted()
}

在 main 中:

println(Coffee().formatted())

输出:

coffee $4.50
challenge icon

挑战

简单

接口 Priced 有一个以美分为单位的 price。为它提供一个默认的 formatted(),返回 $4.50,再提供一个默认的 isAffordable(budget),返回价格是否不高于预算。Coffee 的价格是 450,并将 formatted() 替换为 coffee $4.50,同时通过 super 复用默认实现。Sandwich(price) 使用这两个默认实现。

提供的代码会读取一个以美分为单位的预算,然后读取内容为 coffee 或 sandwich,650 的多行输入。对于每件商品,它会输出 formatted() 的结果,以及 yes 或 no。

你的代码应写在 Priced.kt、Coffee.kt 和 Sandwich.kt 中。Main.kt 包含提供的输入/输出代码,不能编辑。

亲手试试

fun main() {
    // 提供的输入输出代码:保持原样
    val input = generateSequence(::readLine).toList()
    val budget = input[0].toInt()
    for (line in input.drop(1)) {
        val p = line.split(",")
        val item: Priced = if (p[0] == "coffee") Coffee() else Sandwich(p[1].toInt())
        println("${item.formatted()} ${if (item.isAffordable(budget)) "yes" else "no"}")
    }
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Kotlin 在线编辑器