- 一个类可以继承另一个类的属性、方法以及其它特性,继承的类叫子类,被继承的类叫父类(或者 超类)。
- 在
Swift
中,继承是区分类与其它类型的重要特征之一。子类可以调用和访问父类的属性、方法和下标,同时也能重写这些方法、属性和下标来优化和修改它们的行为。 - 我们也可以为类中继承来的属性添加属性观察器,这样一来,当属性值改变时,类就会被通知到。可以为任何属性添加属性观察器,无论它原本被定义为存储型属性还是计算型属性。
定义一个基类
不能继承于其它类的类被称为基类,如Objective-C中
的NSObject
就是一个基类。但在Swift
中类并不是从一个通用的基类继承而来的,如果你不为定义的类指定一个父类,那么它就会自动成为基类。
请看下面的例子
class Vehicle
{
var currentSpeed:Double = 0.0
var description:String
{
return "Traveling at \(currentSpeed) miles per hour."
}
func makeNoise()
{
//在这里什么都不做
}
}
如上,我们定义了一个基类Vehicle(交通工具)
,它包含一个存储型属性currentSpeed
和一个只读的计算型属性description
,同时还有一个方法makeNoise()
.
生成一个子类(子类生成)
子类生成指:在已有类的基础上生成一个新的类,该子类具有父类的特性,并且可以进一步完善和新的特性。
语法:
class name : super class
{
code
}
请看下面的例子:
//子类
class Bicycle: Vehicle
{
var hasBasket:Bool = false
}
let bicycle = Bicycle.init()
bicycle.hasBasket = true
bicycle.currentSpeed = 88.88
print("\(bicycle.description)")
bicycle.makeNoise()
输出结果
The bicycle does have basket.
Traveling at 88.88 miles per hour.
Program ended with exit code: 0
我们定义一个自行车Bicycle
的子类,继承自Vehicle
,如上,它拥有Vehicle
的所有特性,并且拥有一个新的属性hasBasket
,同时它还能修改从Vehicle
继承而来的currentSpeed
属性。
重写
重写指:子类可以为继承来的实例方法、类方法、实例属性或者下标提供自己定制的实现。
在需要重写的特性前面加上override关键字,表明该特性是重写版本的,而非错误提供的相同的版本。任何缺少override关键字的重写,在编译时都会被诊断为错误。
1.访问父类的方法、属性或下标
在合适的地方,我们可以通过使用super
前缀来访问超类版本的方法,属性或下标:
1.在方法
someMethod()
的重写实现中,可以通过super.someMethod()
来调用超类版本的someMethod()
方法。
2.在属性someProperty
的getter
或setter
的重写实现中,可以通过super.someProperty
来访问超类版本的someProperty
属性。
3.在下标的重写实现中,可以通过super[someIndex]
来访问超类版本中的相同下标。
2.重写方法
如下,我们在Bicycle
方法中重写makeNoise( )
方法,
class Bicycle: Vehicle
{
var hasBasket:Bool = false
override func makeNoise()
{
print("This is override functon")
}
}
运行结果
The bicycle does have basket.
Traveling at 88.88 miles per hour.
This is override functon
Program ended with exit code: 0
3.重写属性
重写属性的getters和setters
无论继承来的属性是存储型的还是计算型的,我们都可以提供定制的getter(或者setter)来重写它。子类并不知道继承来的属性是存储型的还是计算型的,它只知道继承来的属性有一个名称和类型。所以,我们在重写属性的是弘扬,必须将它的名字和类型都写出来。
如下,我们在Bycicle
中重写Vehicle
的description:String
属性
override var description: String
{
return super.description + "And it is \(currentSpeed >= 60 ? "":"not") overspeed"
}
注意:
我们可以将一个继承来的只读属性重写为一个读写属性,只需要在重写版本的属性里提供
getter
和setter
即可。但是,你不可以将一个继承来的读写属性重写为一个只读属性。因为如果我们在重写属性中提供了setter
,那么你也一定要提供getter
。如果你不想在重写版本中的getter
里修改 继承来的属性值,你可以直接通过super.someProperty
来返回继承来的值,其中someProperty
是你要重写的属性的名字。
重写属性观察器
我们可以通过重写属性为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,我们就会被 通知到,无论那个属性原本是如何实现的。
有下面两点需要注意
- 我们不可以为继承来的常量型属性或者只读型计算属性添加属性观察器,因为他们是不可改变的。
- 此外,我们也不可以同时提供重写的setter和属性观察器,如果想观察属性值的变化,可以在已经提供的定制setter中观察任何值的变化。
如下例子
class Car: Vehicle
{
var gear:Int = 1
override var currentSpeed: Double
{
didSet
{
gear = Int(currentSpeed/10) + 1
}
}
override var description: String
{
return super.description + "in gear \(gear)"
}
}
let car = Car.init()
car.currentSpeed = 35.88
print("\(car.description)")
运行结果
Traveling at 35.88 miles per hour.in gear 4
Program ended with exit code: 0
在上面的例子中,我们重写了currentSpeed
属性,添加了属性观察器,在属性观察器中,每次currentSpeed
的值发生变化,就会更新gear
的值。
防止重写
- 我们可以使用
final
关键字来标记方法 、属性或下标,来防止它们被重写。 - 如果重写了带有
final
标记的方法、属性或下标,在编译时会报错。在类扩展中的方法,属性或下标也可以在 扩展的定义里标记为final
的。 - 你可以通过在关键字
class
前添加final
修饰符来将整个类标记为final
的。这样的类是不可 被继承的,试图继承这样的类会导致编译报错。
如下例子:
final class Car: Vehicle
{
final var gear:Int = 1
final func makeTimes()
{
print("Final function")
}
override var currentSpeed: Double
{
didSet
{
gear = Int(currentSpeed/10) + 1
}
}
override var description: String
{
return super.description + "in gear \(gear)"
}
}
网友评论