首页 Swift中的继承
文章
取消

Swift中的继承

什么是继承?

继承是一种通过从已有类创建新类来扩展功能的方式。在这个过程中,新类会自动继承已有类的所有属性和方法,并可以根据需要添加或重写这些属性和方法以满足自身的需求。在Swift中,继承通过class关键字来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Vehicle {
    var currentSpeed = 0.0
    
    func accelerate() {
        currentSpeed += 10.0
    }
    
    func brake() {
        currentSpeed -= 10.0
    }
}

class Bicycle: Vehicle {
    var hasBasket = false
}

let bicycle = Bicycle()
bicycle.accelerate()

在上述代码中,我们定义了一个Vehicle类来表示交通工具,包含当前速度属性和加速/刹车方法。之后,我们又定义了一个Bicycle类,它从Vehicle类继承而来,并增加了一个hasBasket属性。最后,我们创建了一个Bicycle实例,并调用其从Vehicle继承而来的accelerate()方法。

子类可以重写(override)父类的方法、属性和下标,以满足自身的需求。为了重写父类中的内容,子类需要使用override关键字进行标记,并在子类中实现自己的版本。在这个过程中,子类可以访问父类中已有的实现,并在其基础上进行修改或扩展。

重写

方法重写

当子类需要重写父类的方法时,可以通过在子类中重新定义该方法来实现。在子类中,使用override关键字来标记需要重写的方法,并且在参数列表和返回值类型上确保与父类中的方法一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vehicle {
    func makeNoise() {
        print("Vroom vroom")
    }
}

class Car: Vehicle {
    override func makeNoise() {
        print("Honk honk")
    }
}

let car = Car()
car.makeNoise() // Output: Honk honk

在上述代码中,我们定义了一个Vehicle类和一个Car类。其中,Vehicle类包含了一个makeNoise()方法,而Car类则从Vehicle类继承而来,并重写了makeNoise()方法。当我们创建一个Car实例并调用其makeNoise()方法时,输出结果为”Honk honk”,这表明Car类成功地重写了父类中的方法。

属性重写

除了方法外,子类还可以重写父类中的属性。当子类需要重写父类的属性时,可以使用override关键字,并在子类中重新定义该属性。在这个过程中,子类可以访问父类中已有的实现,并在其基础上进行修改或扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vehicle {
    var speed: Double {
        return 0.0
    }
}

class Car: Vehicle {
    override var speed: Double {
        return 100.0
    }
}

let car = Car()
print(car.speed) // Output: 100.0

在上述代码中,我们定义了一个Vehicle类和一个Car类。其中,Vehicle类包含了一个speed属性,而Car类则从Vehicle类继承而来,并重写了speed属性。当我们创建一个Car实例并调用其speed属性时,输出结果为100.0,这表明Car类成功地重写了父类中的属性。

下标重写

在Swift中,子类同样可以重写父类的下标。当子类需要重写父类的下标时,可以使用override关键字,并在子类中重新定义该下标。在这个过程中,子类可以访问父类中已有的实现,并在其基础上进行修改或扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vehicle {
    subscript(index: Int) -> String {
        return "Super vehicle"
    }
}

class Car: Vehicle {
    override subscript(index: Int) -> String {
        return "Super car"
    }
}

let car = Car()
print(car[0]) // Output: Super car

在上述代码中,我们定义了一个Vehicle类和一个Car类。其中,Vehicle类包含了一个下标,而Car类则从Vehicle类继承而来,并重写了该下标。当我们创建一个Car实例并调用其下标时,输出结果为”Super car”,这表明Car类成功地重写了父类中的下标。

继承的优点

继承作为一种面向对象编程的基础概念,在Swift中同样有着许多优点:

  • 代码复用性: 继承可以让子类自动拥有父类的属性和方法,减少了代码重复的情况,也方便了代码的维护和修改。
  • 代码灵活度: 子类可以根据需要对父类的属性和方法进行重写或添加,使得代码更加适应不同的场景。
  • 代码可扩展性: 继承可以通过创建子类并在其中添加新方法或属性,来扩展已有类的功能。
  • 代码组织性: 继承可以将相似的对象归为一类,方便后续的管理和维护。

继承的限制

尽管继承非常有用,但是在使用时仍然需要考虑一些限制和注意事项。

  • 继承链的长度: 过长的继承链可能会导致代码变得难以理解和维护,因此应该尽量避免过度继承的情况。
  • 构造器的要求: 如果子类没有定义任何指定构造器,那么它会自动继承所有父类的指定构造器。如果父类中只定义了便利构造器,则子类必须实现至少一个指定构造器以确保初始化安全性。
  • 方法重载的影响: 如果子类重载了一个父类的方法,那么在调用该方法时需要特别小心。这是因为子类的实例也可以看做是父类的实例,因此在某些情况下可能会出现意料之外的结果。
  • 属性观察者的限制: 子类无法为继承来的属性添加属性观察者,但是可以重写已有的属性并为其添加属性观察者。

继承的实践

接下来介绍一些使用继承的实践技巧。

使用super关键字

在子类中,如果需要访问父类中的属性或方法,可以使用super关键字来实现。具体而言,super可以用于:

  • 在子类中调用父类中的指定构造器。
  • 在子类中调用父类中的方法、属性、下标等。
  • 在重载父类方法时调用父类的实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func introduce() {
        print("My name is \(name)")
    }
}

class Student: Person {
    var grade: Int
    
    init(name: String, grade: Int) {
        self.grade = grade
        super.init(name: name)
    }
    
    override func introduce() {
        super.introduce()
        print("I am a student in grade \(grade)")
    }
}

let student = Student(name: "Tom", grade: 5)
student.introduce()

在上述代码中,我们定义了一个Person类和一个Student类。其中,Student类从Person类继承而来,并增加了一个grade属性。在Student类中,我们通过调用super.init(name:)来调用父类的指定构造器,以确保子类初始化完成。在Student类中,我们还重写了父类的introduce()方法,并通过super.introduce()来调用父类中的实现。

使用final关键字

在Swift中,如果不希望某个类被其他类继承,则可以使用final关键字来修饰该类。这样一来,在其他类中尝试继承该类时,编译器会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
final class Vehicle {
    var currentSpeed = 0.0
    
    func accelerate() {
        currentSpeed += 10.0
    }
    
    func brake() {
        currentSpeed -= 10.0
    }
}

class Bicycle: Vehicle { // Error: Inheritance from a final class 'Vehicle'
    var hasBasket = false
}

在上述代码中,我们将Vehicle类声明为final,因此在Bicycle类中尝试继承它时,编译器会报错。

使用多层继承

在Swift中,子类也可以作为父类再次被继承,从而形成更加复杂的继承结构。例如,我们可以定义一个Car类,它从Vehicle类继承而来,并增加了一些新的属性和方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Car: Vehicle {
    var brand: String
    
    init(brand: String) {
        self.brand = brand
    }
    
    func honk() {
        print("\(brand) car honks")
    }
}

let car = Car(brand: "BMW")
car.accelerate()
car.honk()

在上述代码中,我们定义了一个Car类,它从Vehicle类继承而来,并增加了一个brand属性和一个honk()方法。通过对Car类进行定义,我们成功地创建了一个多层继承的继承结构。

本文由作者按照 CC BY 4.0 进行授权

Swift中的方法(Methods)

Swift中的初始化