首页 > 代码库 > 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 -- 继承