Menu
CoddyTech

final 与继承层次结构

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

final 会阻止进一步的重写。final func 不能在任何子类中重写,而 final class 完全不能被继承:

class Account {
    final func id() -> String { "ACC" }   // 不能被重写
}

final class Receipt { }                  // 不能被继承
// class GiftReceipt: Receipt { }        // 错误:不能继承 final 类

当子类不得更改某个方法时,将其标记为 final,例如用于强制执行规则的方法。其他方法仍可被重写,以自定义细节:

class Checkout {
    final func total(_ prices: [Int]) -> Int {
        let sum = prices.reduce(0, +)
        return sum - discount(sum)
    }
    func discount(_ sum: Int) -> Int { 0 }
}

class SaleCheckout: Checkout {
    override func discount(_ sum: Int) -> Int { sum / 10 }
}

print(Checkout().total([50, 50]))
print(SaleCheckout().total([50, 50]))

输出:

100
90

继承层次可以有多个层级。查找方法时,会从对象自己的类开始,逐级向上查找,并运行找到的第一个实现:

class Animal {
    func move() -> String { "moves" }
    func eat() -> String { "eats" }
}
class Bird: Animal {
    override func move() -> String { "flies" }
}
class Penguin: Bird {
    override func move() -> String { "swims" }
}

let p = Penguin()
print(p.move())
print(p.eat())

输出:

swims
eats

保持继承层级浅一些。继承链太深会难以理解,因为一个对象的行为分散在许多类中。如果类型共享行为,但不存在“is-a”关系,通常用协议(下一章)会更合适。

// 继承层级深,而且很脆弱
class A { }
class B: A { }
class C: B { }
class D: C { }      // D 继承了什么?从哪里继承的?
challenge icon

挑战

简单

Discount 有一个 final 方法 apply(to:),它返回价格减去 amount(for:) 后的结果,但不会低于 0;amount(for:) 返回 0。声明 PercentOff(存储 percent,金额 = 价格乘以百分比再除以 100)和 FixedOff(存储 value,金额 = value),两者都要有初始化器,并重写 amount(for:)。apply(to:) 本身保留在 Discount 中。

提供的代码会读取价格,然后读取折扣 p,10 或 f,300,将每个折扣应用到价格上,并打印 1000 -> 900。

你的代码要写在 Discount.swift、PercentOff.swift 和 FixedOff.swift 中。main.swift 包含提供的输入/输出代码,不能编辑。

亲手试试

// 提供的输入/输出代码:保持原样。
var input: [String] = []
while let line = readLine() { input.append(line) }
let price = Int(input[0])!
for line in input.dropFirst() {
    let p = line.split(separator: ",").map(String.init)
    let d: Discount = p[0] == "p" ? PercentOff(percent: Int(p[1])!) : FixedOff(value: Int(p[1])!)
    print("\(price) -> \(d.apply(to: price))")
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Swift 在线编辑器