初始化器与 super
本课属于 Coddy Swift 学习旅程的“面向对象编程”单元。第 24 课,共 57 课。
当子类添加没有默认值的存储属性时,它需要自己的初始化器。它会先设置自己的属性,然后使用 super.init(...) 调用超类初始化器:
class Animal {
let name: String
init(name: String) { self.name = name }
}
class Bird: Animal {
let canFly: Bool
init(name: String, canFly: Bool) {
self.canFly = canFly
super.init(name: name)
}
}
let p = Bird(name: "Pip", canFly: false)
print("\(p.name) \(p.canFly)")输出:
Pip false顺序很重要:子类属性必须先有值,super.init 才能运行;继承的属性只能在它运行后使用。Swift 会在编译时检查这一点:
init(name: String, canFly: Bool) {
// print(self.name) // 错误:在 super.init 之前使用了 self
self.canFly = canFly // 1. 自身的属性
super.init(name: name) // 2. 父类
print(self.name) // 3. 现在可以使用所有内容了
}子类定义了自己的初始化器后,就不再继承超类的初始化器。子类也可以使用相同的参数重写初始化器,并将其标记为 override init:
class Timer {
var seconds: Int
init(seconds: Int) { self.seconds = seconds }
}
class SafeTimer: Timer {
override init(seconds: Int) {
super.init(seconds: max(0, seconds))
}
}
print(SafeTimer(seconds: -5).seconds)
print(SafeTimer(seconds: 30).seconds)输出:
0
30层级中的每一层都会初始化自己的部分,并将剩余部分交给它的超类,因此继承链中的每个属性都会且仅会获得一次值:
class Vehicle {
let wheels: Int
init(wheels: Int) { self.wheels = wheels }
}
class Car: Vehicle {
let seats: Int
init(seats: Int) {
self.seats = seats
super.init(wheels: 4)
}
}
class Taxi: Car {
let company: String
init(company: String) {
self.company = company
super.init(seats: 5)
}
}
let t = Taxi(company: "City Cabs")
print("\(t.company): \(t.wheels) wheels, \(t.seats) seats")输出:
City Cabs: 4 wheels, 5 seats挑战
简单Product 用于存储 name 和 price(单位为美分)。声明子类 DiscountedProduct,其中包含存储属性 percent。它的初始化器接收 name、price 和 percent,存储 percent,并使用已按百分比折扣后的价格(向下取整)调用 super.init。超出 0-100 范围的 percent 按 0 处理。在 DiscountedProduct 中添加方法 label(),返回 tea: 450 (10% off)。
提供的代码会读取格式为 name,price,percent 的行,为每行创建一个 DiscountedProduct,并打印 label()。
你的代码写在 Product.swift 和 DiscountedProduct.swift 中。main.swift 包含提供的输入/输出代码,不能编辑。
亲手试试
// 提供的输入/输出代码:保持原样
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
let p = line.split(separator: ",").map { String($0) }
let item = DiscountedProduct(name: p[0], price: Int(p[1])!, percent: Int(p[2])!)
print(item.label())
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Swift 在线编辑器