Menu
CoddyTech

子类

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

继承可以让一个类基于另一个类构建。class Dog: Animal会让Dog成为超类Animal的子类:狗拥有动物的所有属性和方法,还拥有Dog添加的内容:

class Animal {
    var name: String
    init(name: String) { self.name = name }
    func describe() -> String { "\(name) is an animal" }
}

class Dog: Animal {
    func fetch() -> String { "\(name) fetches the ball" }
}

let rex = Dog(name: "Rex")
print(rex.describe())
print(rex.fetch())

输出:

Rex is an animal
Rex fetches the ball

没有添加存储属性的子类会继承超类的初始化器,因此在 Dog 中没有 init,Dog(name:) 也能正常使用。继承表示“是一个”的关系:每只狗都是一种动物,因此在需要 Animal 的地方都可以使用 Dog:

class Animal {
    var name: String
    init(name: String) { self.name = name }
}

class Cat: Animal {}
class Dog: Animal {}

let pets: [Animal] = [Cat(name: "Tom"), Dog(name: "Rex")]
for pet in pets { print(pet.name) }

输出:

Tom
Rex

只有类支持继承;结构体和枚举不能继承。一个类最多只能有一个父类,但一个父类可以有多个子类,从而形成层次结构:

class Vehicle { var wheels = 0 }
class Car: Vehicle { }        // Car 是一种 Vehicle
class Bike: Vehicle { }       // Bike 是一种 Vehicle
// struct Truck: Vehicle { }  // 错误:结构体不能继承

把所有子类共有的内容放在超类中,只把各个子类的差异放在子类中。如果一种类型实际上并不是另一种类型的一种,那么继承就不是合适的工具;通常用一个属性来保存另一种类型会更合适。

class Shape {
    var name: String
    init(name: String) { self.name = name }
    func label() -> String { "a \(name)" }
}

class Square: Shape {
    var side = 1.0
    func area() -> Double { side * side }
}

let s = Square(name: "square")
s.side = 3
print(s.label())
print(s.area())

输出:

a square
9.0
challenge icon

挑战

简单

Employee 用于存储 name 和 salary,并有一个方法 raise(by:),可以按百分比提高薪水(向下取整)。声明一个子类 Manager,添加一个存储属性 reports(用于存储姓名的数组,初始为空)、一个方法 addReport(_:),以及一个返回报告人数的方法 teamSize()。

提供的代码会根据第一行(name,salary)创建一位经理,将之后的每个姓名添加为报告对象,涨薪 10%,并打印 Ada earns 5500 and leads 2。

你的代码写在 Employee.swift 和 Manager.swift 中。main.swift 中包含提供的输入/输出代码,不能编辑。

亲手试试

// 提供的输入/输出代码:保持原样。
var input: [String] = []
while let line = readLine() { input.append(line) }
let head = input[0].split(separator: ",").map(String.init)
let boss = Manager(name: head[0], salary: Int(head[1])!)
for name in input.dropFirst() { boss.addReport(name) }
boss.raise(by: 10)
print("\(boss.name) earns \(boss.salary) and leads \(boss.teamSize())")
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Swift 在线编辑器