首页 > 代码库 > swift 学习- 14 -- 继承
swift 学习- 14 -- 继承
// 一个类可以继承另一个 类的方法, 属性和其他特征, 当一个类继承其他类时, 继承类叫子类, 被继承类叫父类 或 (超类), 在 Swift 中, 继承是区分 [类] 和其他类型的 一个基本特征
// 在 Swift 中, 类可以调用和访问超类的方法, 属性 和 下标, 并且可以重写这些方法, 属性 和 下标来优化或修改他们的行为
// Swift 会检查你的重写定义在超类中是否有匹配的定义, 一次确保你的重写行为是正确的
// 可以为类中继承来的属性添加属性观察器, 这样一来, 当属性值改变时, 类就会被通知到, 可以为 任意属性 添加 属性观察器,无论他原本被定义为 存储属性 还是 计算属性
// 定义一个基类
// 不继承于其他类的类, 称之为 基类
// 注意 : Swift 中的类并不是 从一个通用的 基类继承而来, 如果你不为你定义的类指定一个 超类 的话, 这个类就自动成为 基类
// 一个例子定义了一个叫做 Vehicle 的基类, 这个基类声明了一个名为 currentSpeed , 默认值是 0.0 的存储属性 (属性类型推断为 Double), currentSpeed 属性的值被一个 String 类型的只读计算型属性 description 使用, 用来创建车辆的描述 . Vehicle 基类也定义了一个名为 makeNoise 的方法, 这个方法实际上部位 Vehicle 实例做任何事, 但之后将会被 Vehicle 的子类定制
class Vehicle{
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// 什么也不作
}
}
let someVehicle = Vehicle()
print("Vehicle: \(someVehicle.description)")
// 子类生成
// 子类生成 指的是在一个已有类的基础上创建一个新的类, 子类继承超类的特性, 并且可以进一步完善, 你还可以为子类添加新的特性
// 为了指明某个类的超类, 将超类名卸载子类名的后面, 用冒号分割:
class Bicycle: Vehicle{
var hasBasket = false
}
// 新的 Bicycle 类自动获得 Vehicle 类的所有属性 和 方法, 除了他所继承的特性, Bicycle 类还定义了一个默认值为 false 的存储属性 hasBasket (Bool 型)
// 默认情况下,你创建的任何新的 Bicycle 实例将不会有一个篮子,但是可以为特定的 Bicycle 实例设置 hasBasket 属性为 ture
let bicycle = Bicycle()
bicycle.hasBasket = true
// 还可以修改 Bicycle 实例所继承的 currentSpeed 属性, 和查询实例所继承的 descriotion 属性:
bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.currentSpeed)")
// 子类还可以继续被其它类所继承 下面的示例为Bicycle创建了一个名为Tandem(双人自行车)的子类:
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 前缀来访问超类版本的方法, 属性 或 下标
// 1: 在方法someMethod()的重写实现中,可以通过super.someMethod()来调用超类版本的someMethod()方法。
// 2: 在属性someProperty的 getter 或 setter 的重写实现中,可以通过super.someProperty来访问超类版本的someProperty属性。
// 3: 在下标的重写实现中,可以通过super[someIndex]来访问超类版本中的相同下标。
// 重写方法
// 在子类中, 你可以重写继承来的实例方法或类方法, 提供一个定制或替代的方法实现
class Train: Vehicle{
override func makeNoise() {
print("Choo Choo")
}
}
// 这个例子定义了 Vehicle 的一个新的子类, 叫 Train, 它重写了从 Vehicle 类继承来的 makeNoise() 方法
let train = Train()
train.makeNoise()
// 重写属性
// 你可以重写继承来的实例属性或类型属性, 提供自己定制的 getter 和 setter,或添加属性观察器 使 重写的属性 也可以观察值什么时候变化
// 重写 属性的 getter 和 setter
// 你可以提供定制的 getter 和 setter 来重写任意继承来的属性, 无论继承来的属性是存储型的 还是 计算型属性, 子类并不知道继承来的属性是 存储型的 还是 计算型的, 它只知道继承来的属性会有一个 名字和类型 , 你在重写一个属性时, 必须将它的 名字和类型 都写出来, 这样才能使编译器 去检查你重写的属性 是否与 超类中同名同类型的属性 相匹配的
// 你可以将一个继承来的 只读属性 重写为 读写属性,只需要在重写版本的属性里 提供 getter 和 setter 即可, 但是,你不能将一个继承来的读写属性 重写为 一个只读属性
// 注意 : 如果你在重写属性中提供了 setter ,那么你也一定要提供 getter, 如果你不想在重写版本中的 getter 里修改继承来的属性值, 你可以直接通过 super.someProperty 来返回继承来的值, 其中 someProperty 是你要重写的属性的名字
class Car: Vehicle{
var gear = 1
override var description: String{
return super.description + " in gear \(gear)"
}
}
// 这个例子定义了一个新类,叫Car,它是Vehicle的子类。这个类引入了一个新的存储型属性叫做gear,默认值为整数1。Car类重写了继承自Vehicle的description属性,提供包含当前档位的自定义描述:
// 重写的 description 属性首先要调用 super.description 返回 Vehicle 类的 description 属性 之后, Car 类版本的 description 在末尾增加了自定义内容
let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)")
// 重写属性观察器
// 你可以通过重写属性为一个 继承来的 属性 添加 属性观察器, 这样一来, 当继承来的属性值发生变化时, 你就会被通知到, 无论哪个属性原本是如何实现的
// 注意 : 你不可以为继承来的常量存储属性 或 继承来的只读计算属性添加 属性观察器, 这些属性的值是不可以被设置的. 所以, 为他们提供 willSet 和 didSet 是不恰当的
// 此外, 你不可以同时提供重写的 setter 和 重写的 属性观察器, 如果你想观察属性值的变化, 并且你已经为那个属性提供了定制的 setter ,那么你在 setter 中就可以观察到任何值的变化了
class AutomaticCar: Car{
override var currentSpeed: Double{
didSet{
gear = Int(currentSpeed / 10.0) + 1
}
}
}
// 当你设置 AutomaticCar 的 currentSprrd 属性, 属性的 didSet 观察器就会自动地设置 gear 属性, 为新的速度选择一个合适的档位, 具体来说, 属性观察器将新的速度值除以 10 ,然后向下取得最接近的整数值, 最后加 1 来得到档位 gear 的值,
let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")
// 防止重写
// 你可以通过把方法,属性 或 下标标记为 final 来防止他们被重写, 只需要在声明关键字前 加上 final 修饰符即可
// 如 : final var , final func, final class func , final subscript
// 如果你重写了带有 final 标记的方法, 属性或者下标, 在编译时或报错,
// 在类扩展中的方法, 属性 或 下标也可以在扩展的定义里标记为 fnial
// 你可以通过在关键字 class 前添加 final 修饰符 (final class) 来将整个类标记为 final 的, 这样的类是不可被继承的, 试图继承这样的类会导致编译错误
swift 学习- 14 -- 继承