美文网首页
Swift 5.1 (13) - 继承

Swift 5.1 (13) - 继承

作者: 沐灵洛 | 来源:发表于2020-02-20 16:57 被阅读0次

    继承

    继承是一种基本行为:子类继承父类方法,属性和其他特性。子类可以重写父类的方法,属性。继承将类与Swift中的其他类型区分开来。
    类还可以将属性观察者添加到继承的存储属性或计算属性上。

    定义一个基类

    基类:定义的任何不从其他类继承的类。Swift中的类在不指定父类的情况下,是不会从通用基类继承,这种情况下构建的类便是开发者定义的基类。

    class BaseClass {
        //....基类的方法,属性等定义
    }
    

    子类

    子类:在现父类基础上构建的新类。子类继承父类的方法,属性和其他特征,并进行差异化操作。

    class SubClass: BaseClass {
        //...继承自`BaseClass`的子类
    }
    

    重写

    重写:子类提供父类的实例方法,类型方法,实例属性,类型属性或下标的自定义实现。
    重写的实现方式:子类要覆盖的继承父类的特性属性或方法前使用override关键字。
    访问父类的方法,属性和下标
    在重写父类的方法,属性和下标时,使用super前缀可以承继父类对于方法,属性和下标的实现。

    class BaseClass {
        
        //....基类的方法,属性等定义
        var something: String {
            get {
                return "i from super"
            }
        }
        func doSomething() -> Void {
        }
        subscript(index:Int)->String {
            return "QiShare"
        }
    }
    class SubClass: BaseClass {
        //...继承自`BaseClass`的子类
        override var something: String {
            return super.something + "+override" //!< 调用输出:i from super+override
        }
        override func doSomething() {
            super.doSomething()
        }
        override subscript(index:Int)->String {
            return super[1] + "/subClass" //!< 调用输出:QiShare/subClass
            
        }
    

    重写属性
    可以覆盖继承的实例或类型属性,为该属性提供自定义的gettersetter,也能添加属性观察者。子类无法知道继承的属性是否计算或存储属性,但知道继承的属性名称和类型。故重写属性时需明确属性的名称和类型。

    1. 重写属性的GetterSetter方法:
    关于重写属性的GetterSetter,官网描述:

    You can provide a custom getter (and setter, if appropriate) to override any inherited property, regardless of whether the inherited property is implemented as a stored or computed property at source。译文:无论继承的属性是在父类中是存储属性还是计算属性,子类都可以提供自定义getter,也可以在场景适用情况下提供setter,用以重写属性

    但是在实际的操作中发现:
    • 继承自父类的存储属性不能被重写。重写时报错:Cannot override with a stored property 'something'。错误示范如下:

    //父类声明常量属性
    let something: String = "QiShare"
    //子类重写常量属性:报错:`Cannot override with a stored property 'something'`
    override let something: String {
        get {
            return "sub+QiShare"
        }
    }
    

    • 继承自父类的变量属性,非计算属性,子类在重写该属性时需要同时提供settergetter。否则编译器报错:Cannot override mutable property with read-only property 'something'。正确示范如下:

    //父类声明变量属性
    var something: String = ""
    //或
    var something: String?
    //子类重写变量属性
    override var something : String {
        get {
            return "子类的实现"
        }
        set{
        }
    }
    

    • 通过重写计算属性GetterSetter方法,子类可将继承自父类的read-only属性变为read-write属性。示例如下:

    //父类声明`read-only`属性
    var something: String {
            get {
                return "i from super"
            }
        }
    //子类重写后变为`read-write`属性
    private var _temp :String = ""
    override var something: String {
        get {
           return super.something + _temp //!< 调用输出:i from super+override
        }
        set {
            _temp = newValue + "subClass override setter"
        }
    }
    //实际调用,确实如此
    let base = BaseClass()
    //base.something = "这句话会报错,因为`sothing`在基类中是只读属性"
    let sub = SubClass()
    sub.something = "子类重写后" //!< i from super子类重写后subClass override setter
    

    • 通过重写计算属性GetterSetter方法,不能将继承自父类的read-write属性变为read-only。个人理解:子类可以增加属性功能,但不能减少属性功能。反其道而行之,编译器报错:Cannot override mutable property with read-only property 'something'

    • 计算属性不管是read-write还是read-only都需要使用var关键字来声明为变量属性。计算属性在组成上由getter和一个可选的setter组成的,即:不管setter有没有,getter都必须有。也因此,若是我们重写了setter方法则必须重写getter方法。基于这种情况getter方法的重写,有时是基于语法的组合体,本质上其实和父类是一样的,那么我们便可以在getter方法中使用super前缀来承继父类的调用。

    2. 重写属性的观察者:
    • 属性可观察的前提是该属性是可变的,故不能在继承的存储属性和read-only属性中添加willSetdidSet。反其道而行之,实际操作中编译器也会报错:Cannot observe read-only property 'something'; it can't change
    • 继承的read-write属性,不能重写setter方法的同时,重写或者添加属性观察器。反其道而行之,在实际操作中编译器会报错:didSetwillSet cannot be provided together with a settergetter

    防止重写

    使用final关键字防止方法,属性或下标被子类重写。具体使用:final varfinal funcfinal class funcfinal subscript

    • 父类使用final关键字修饰过的方法,属性或下标,子类重写时编译器便会报错。
    • 在类扩展中使用final关键字修饰过的方法,属性或下标也同样生效。
    • 在类定义时的class关键字之前使用final关键字,来将整个类的方法,属性或下标标记为子类不可重写。

    参考资料:
    swift 5.1官方编程指南

    相关文章

      网友评论

          本文标题:Swift 5.1 (13) - 继承

          本文链接:https://www.haomeiwen.com/subject/nlihjctx.html