继续学习Swift文档,从上一章节:下标,咱们学习了Swift下标相关的内容,以下标语法、下标用法、下标选项和类型下标等这些内容。如今,咱们学习Swift的继承相关的内容。因为篇幅较长,这里分篇来记录,接下来,Fighting!html
熟悉这一章节的朋友能够直接跳过下一章节:初始化swift
一个类能够从另外一个类继承方法,属性和其余特征。 当一个类从另外一个类继承时,继承的类称为子类,而其继承的类称为其父类。 继承是一种基本行为,可将Swift中的类与其余类型区分开。bash
Swift中的类能够调用和访问属于其父类的方法,属性和下标,并能够提供这些方法,重写属性和下标以完善或修改其行为。 Swift经过检查覆盖定义是否具备匹配的父类定义来帮助确保覆盖是正确的。ide
类还能够将属性观察器添加到继承的属性中,以便在属性值更改时获得通知。 能够将属性观察器添加到任何属性,而无论其最初是定义为存储属性仍是计算属性。post
任何不从另外一个类继承的类都称为基类。性能
注意
Swift类不能从通用基类继承。 您没有指定父类而定义的类将自动成为基类供您构建。学习
下面的示例定义了一个称为Vehicle的基类。 该基类定义了一个称为currentSpeed的存储属性,默认值为0.0(推断属性类型为Double)。 currentSpeed属性的值由一个称为description的只读计算出的String属性用于建立车辆的描述。优化
Vehicle基类还定义了一个称为makeNoise的方法。 此方法实际上不对基础Vehicle实例执行任何操做,但稍后将由Vehicle的子类自定义:ui
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// do nothing - an arbitrary vehicle doesn't necessarily make a noise } } 复制代码
使用初始化器语法建立一个Vehicle的新实例,该实例被写为类型名称,后跟空括号:spa
let someVehicle = Vehicle()
复制代码
建立新的Vehicle实例后,您能够访问其description属性,以打印出人类能够理解的车辆当前速度的描述:
print("Vehicle: \(someVehicle.description)")
// Vehicle: traveling at 0.0 miles per hour
复制代码
Vehicle类定义了任意车辆的共同特征,但其自己并无太多用途。 为了使其更有用,您须要对其进行改进以描述更多特定类型的车辆。
子类化是在现有类的基础上创建新类的行为。 子类继承现有类的特征,而后能够对其进行优化。 您还能够向子类添加新特征。
要代表子类具备父类,请在父类名称以前写上子类名称,并用冒号分隔:
class SomeSubclass: SomeSuperclass {
// subclass definition goes here
}
复制代码
下面的示例定义了一个名为Bicycle的子类,并带有Vehicle的父类:
class Bicycle: Vehicle {
var hasBasket = false
}
复制代码
新的Bicycle类自动得到了Vehicle的全部特征,例如currentSpeed和description属性以及makeNoise()方法。
除其继承的特征外,Bicycle类还定义了一个新的存储属性hasBasket,其默认值为false(为该属性推断为Bool类型)。
默认状况下,您建立的任何新Bicycle实例都没有篮子。 建立特定的Bicycle实例后,能够将hasBasket属性设置为true:
let bicycle = Bicycle()
bicycle.hasBasket = true
复制代码
您还能够修改Bicycle实例的继承的currentSpeed属性,并查询该实例的继承的description属性:
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)")
// Bicycle: traveling at 15.0 miles per hour
复制代码
子类自己能够被子类化。 下一个示例为称为“双人”的两人座自行车建立Bicycle的子类:
class Tandem: Bicycle {
var currentNumberOfPassengers = 0
}
复制代码
Tandem继承了Bicycle的全部属性和方法,然后者又继承了Vehicle的全部属性和方法。 Tandem子类还添加了一个名为currentNumberOfPassengers的新存储属性,默认值为0。
若是建立Tandem实例,则可使用它的任何新属性和继承的属性,并查询它从Vehicle继承的只读description属性:
let tandem = Tandem()
tandem.hasBasket = true
tandem.currentNumberOfPassengers = 2
tandem.currentSpeed = 22.0
print("Tandem: \(tandem.description)")
// Tandem: traveling at 22.0 miles per hour
复制代码
子类能够提供其本身的实例方法,类型方法,实例属性,类型属性或下标的自定义实现,不然该实例方法将从超类继承。 这称为重写。
要重写本来会被继承的特征,请在您的重写定义前添加override关键字。 这样作能够明确您打算提供替代,而且没有错误地提供匹配的定义。 偶然的重写可能会致使意外的行为,而且在编译代码时,任何不带有override关键字的替代都会被诊断为错误。
Override关键字还会提示Swift编译器检查您的重写类的父类(或其父类之一)是否具备与您为该替代提供的声明相匹配的声明。 此检查可确保您的重写定义正确。
当为子类提供方法,属性或下标替代时,将现有的超类实现用做替代的一部分有时会颇有用。 例如,您能够优化该现有实现的行为,或者将修改后的值存储在现有的继承变量中。
在适当的状况下,您可使用super前缀访问方法,属性或下标的超类版本:
您能够重写继承的实例或类型方法,以在子类中提供该方法的定制或替代实现。
如下示例定义了一个名为Train的Vehicle的新子类,该子类重写Train从Vehicle继承的makeNoise()方法:
class Train: Vehicle {
override func makeNoise() {
print("Choo Choo")
}
}
复制代码
若是建立一个Train的新实例并调用其makeNoise()方法,则能够看到该方法的Train子类版本称为:
let train = Train()
train.makeNoise()
// Prints "Choo Choo"
复制代码
您能够重写继承的实例或类型属性,觉得该属性提供本身的自定义getter和setter,或添加属性观察器以使重写的属性可以在基础属性值更改时进行观察。
重写属性的Getters和Setters 您能够提供一个自定义getter(若是合适的话,可使用setter)来重写任何继承的属性,而无论该继承的属性是在源上实现为存储属性仍是计算属性。 子类不知道继承属性的存储或计算性质,它仅知道继承属性具备特定名称和类型。 您必须始终声明要重写的属性的名称和类型,以使编译器可以检查您的重写是否与具备相同名称和类型的父类属性匹配。
经过在子类属性重写中同时提供getter和setter,能够将继承的只读属性呈现为读写属性。 可是,您不能将继承的读写属性表示为只读属性。
注意
若是在属性替代中提供了一个setter,则还必须为该替代提供一个getter。 若是您不想在重写的getter中修改继承的属性的值,则能够经过从getter返回super.someProperty来传递继承的值,其中someProperty是您要重写的属性的名称。
如下示例定义了一个名为Car的新类,它是Vehicle的子类。 Car类引入了一个称为gear的新存储属性,其默认整数值为1。Car类还覆盖了它从Vehicle继承的description属性,以提供包括当前gear的自定义描述:
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}
复制代码
对description属性的重写是经过调用super.description开始的,super.description返回Vehicle类的description属性。 而后,汽车类的描述版本会在此描述的末尾添加一些额外的文字,以提供有关当前装备的信息。
若是建立Car类的实例并设置其gear和currentSpeed属性,则能够看到其description属性返回在Car类中定义的定制描述:
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
// Car: traveling at 25.0 miles per hour in gear 3
复制代码
重写属性监听 您可使用属性重写将属性观察器添加到继承的属性。 这使您能够在继承属性的值更改时获得通知,而不管该属性最初是如何实现的。 有关属性观察器的更多信息,请参见Property Observers。
注意
您不能将属性观察器添加到继承的常量存储属性或继承的只读计算属性。 这些属性的值没法设置,所以不建议将willSet或didSet实现做为覆盖的一部分提供。
还要注意,您不能为同一属性同时提供覆盖设置器和覆盖属性观察器。 若是您想观察属性值的变化,而且已经在为该属性提供自定义设置器,则能够简单地观察自定义设置器中的任何值更改。
下面的示例定义一个名为AutomaticCar的新类,它是Car的子类。 AutomaticCar类表明具备自动变速箱的汽车,该变速箱会根据当前速度自动选择要使用的档位:
class AutomaticCar: Car {
override var currentSpeed: Double {
didSet {
gear = Int(currentSpeed / 10.0) + 1
}
}
}
复制代码
每当您设置AutomaticCar实例的currentSpeed属性时,该属性的didSet观察器都会将该实例的gear属性设置为新速度的适当齿轮。 具体来讲,属性观察者选择的齿轮是新的currentSpeed值除以10,四舍五入到最接近的整数加1。35.0的速度产生4的齿轮:
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// AutomaticCar: traveling at 35.0 miles per hour in gear 4
复制代码
您能够经过将方法,属性或下标标记为final来防止其被重写。 为此,能够在方法,属性或下标的Introductionr关键字(例如final var,final func,final class func和final下标)以前编写final修饰符。
尝试重写子类中的最终方法,属性或下标的任未尝试都将报告为编译时错误。 您在扩展程序的类中添加的方法,属性或下标也能够在扩展程序的定义中标记为final。
您能够经过在类定义中的class关键字以前编写final修饰符,将整个类标记为(final class)。 任未尝试将最终类做为子类的尝试都将报告为编译时错误。
这一章节主要讲的是:
好了,有收获的朋友麻烦给个鼓励哦,谢谢啦~
参考文档: Swift - Inheritance