一个类可以从另外一个类中继承方法,属性或者其它的一些特性。当一个类继承于另外一个类时,这个继承的类叫子类,被继承的类叫父类。继承是Swift中类区别于其它类型的一个基本特征。
Swift中的类可以调用父类的方法,使用父类的属性和下标,还可以根据需要使用重写方法或者属性来重新定义和修改他们的一些特性。Swift可以帮助你检查重写的方法和父类的方法定义是相符的。
类还可以为它继承的属性添加观察者,这样可以能够让它在一个属性变化的时候得到通知。属性观察者可以被添加给任何属性,不管它之前是存储属性还是计算属性。
1、定义一个基类
任何一个不继承于其它类的类被称作基类
注意:Swift的类不是从一个全局基类继承而来。在你编写代码的时,只要是在类的定义中没有继承自父类的类都是基类。
下面的例子定义了一个叫Vehicle的基类。基类包含两个所有交通工具通用的属性numberOfWheels和maxPassengers。这两个属性被一个叫description的方法使用,通过返回一个String描述来作为这个交通工具的特征:
class Vehicle {
var numberOfWheels: Int
var maxPassengers: Int
func description() -> String {
return "\(numberOfWheels) wheels; up to \(maxPassengers) passengers"
}
init() {
numberOfWheels = 0
maxPassengers = 1
}
}
</div>
这个交通工具类Vehicle还定义了一个构造函数来设置它的属性。构造函数更多的解释在Initialization一章,但是为了说明子类如何修改继承的属性,这里需要简要解释一下什么叫构造函数。
通过构造函数可以创建一个类型的实例。尽管构造函数不是方法,但是它们在编码的时候使用了非常相似的语法。构造函数通过确保所有实例的属性都是有效的来创建一个新的实例。
构造函数最简单的形式是使用init关键词的一个类似方法的函数,并且没有任何参数:
init() {
// perform some initialization here
}
</div>
使用构造函数语法TypeName和空的两个小括号来完成一个Vehicle实例的创建:
let someVehicle = Vehicle()
</div>
Vehicle的构造函数为属性设置了一些初始值(numberOfWheels = 0 然后 maxPassengers = 1)。
Vehicle类定义的是一个通用的交通工具特性,它本身没有太多意义,所以就需要冲定义它的一些属性或者方法来让它具有实际的意义。
2、产生子类
产生子类就是根据一个已有的类产生新类的过程。子类继承了父类的一些可以修改的特性。还可以为子类添加一些新的特性。
为了表明一个类是继承自一个父类,需要将父类的名称写在子类的后面,并且用冒号分隔:
class SomeClass: SomeSuperclass {
// class definition goes here
}
</div>
下面的例子定义了一种特定叫Bicycle的交通工具。这个新类是基于已有的类Vehicle产生的。书写方式是在类名Bicycle后加冒号加父类Vehicle名。
可以理解为:
定义一个新的类叫Bicycle,它继承了Vehicle的特性:
class Bicycle: Vehicle {
init() {
super.init()
numberOfWheels = 2
}
}
</div>
Bicycle是Vehicle的子类,Vehicle是Bicycle的父类。Bicycle类继承了Vehicle所有的特征,比如maxPassengers和numberOfWheels属性。你还可以为Bicycle类添加心的属性。
Bicycle类也定义了构造函数,在这个构造函数中调用了父类的构造函数super.init(),这样可以确保在Bicycle修改他们之前,父类已经初始化了。
注意:跟Objective-C不同的是,Swift中的构造函数没有默认继承。更多信息可以参考Initializer Inheritance and Overriding这一章节。
maxPassengers属性在继承自父类的时候已经被初始化了,对于Bicycle来说是正确的,因此不需要再做更改。然后numberOfWheels是不对的,所以被替换成了2.
不仅属性是继承于Vehicle的,Bicycle还继承了父类的方法。如果你创建一个实例,然后调用了已经继承的description方法,可以得到该交通工具的描述并且看到它的属性已经被修改:
let bicycle = Bicycle()
println("Bicycle: \(bicycle.description())")
// Bicycle: 2 wheels; up to 1 passengers
</div>
子类本身也可以作为父类被再次继承:
class Tandem: Bicycle {
init() {
super.init()
maxPassengers = 2
}
}
</div>
上面的例子创建了Bicycle的子类,叫做tandem,也就可以两个人一起骑的自行车。所以Tandem没有修改numberOfWheels属性,只是更新了maxPassengers属性。
注意:子类只能够在构造的时候修改变量的属性,不能修改常量的属性。
创建一个Tandem的实例,然后调用description方法检查属性是否被正确修改:
let tandem = Tandem()
println("Tandem: \(tandem.description())")
// Tandem: 2 wheels; up to 2 passengers
</div>
注意到description方法也被Tandem继承了。
3、重写方法
子类可以提供由父类继承来的实例方法,类方法,实例属性或者下标的个性化实现。这个特性被称为重写。
重写一个由继承而来的方法需要在方法定义前标注override关键词。通过这样的操作可以确保你所要修改的这个方法确实是继承而来的,而不会出现重写错误。错误的重写会造成一些不可预知的错误,所以如果如果不标记override关键词的话,就会被在代码编译时报错。
override关键词还能够让Swift编译器检查该类的父类是否有相符的方法,以确保你的重写是可用的,正确的。
访问父类方法,属性和下标
当在重写子类继承自父类的方法,属性或者下标的时候,需要用到一部分父类已有的实现。比如你可以重定义已知的一个实现或者在继承的变量中存储一个修改的值。
适当的时候,可以通过使用super前缀来访问父类的方法,属性或者下标:
叫someMethod的重写方法可以在实现的时候通过super.someMethod()调用父类的someMethod方法。
叫someProperty的重写属性可以在重写实现getter或者setter的时候通过super.someProperty调用父类的someProperty。
叫someIndex的重写下标可以在实现下标的时候通过super[someIndex]来访问父类的下标。
复写方法
你可以在你的子类中实现定制的继承于父类的实例方法或者类方法。
下面的例子演示的就是一个叫Car的Vehicle子类,重写了继承自Vehicle的desc