阅读 430

Swift 5.1 (13) - 继承

级别: ★☆☆☆☆
标签:「iOS」「Swift 5.1」「继承」
作者: 沐灵洛
审校: QiShare团队


继承

继承是一种基本行为:子类继承父类方法,属性和其他特性。子类可以重写父类的方法,属性。继承将类与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官方编程指南


小编微信:可加并拉入《QiShare技术交流群》。

关注我们的途径有:
QiShare(简书)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公众号)

推荐文章:
WebSocket 双端实践(iOS/ Golang)
今天我们来聊一聊WebSocket(iOS/Golang)
用 Swift 进行贝塞尔曲线绘制
Swift 5.1 (11) - 方法
Swift 5.1 (10) - 属性
iOS App后台保活
奇舞周刊

关注下面的标签,发现更多相似文章
评论