Swift 继承

       一个类可以继承(inherit)另一个类的方法(methods),属性(properties)和其它特性。当一个类继承其它类时,继承类叫子类(subclass),被继承类叫超类(或父类,superclass)。在 Swift 中,继承是区分「类」与其它类型的一个基本特征。

        在 Swift 中,类可以调用和访问超类的方法,属性和下标脚本(subscripts),并且可以重写(override)这些方法,属性和下标脚本来优化或修改它们的行为。Swift 会检查你的重写定义在超类中是否有匹配的定义,以此确保你的重写行为是正确的。

        可以为类中继承来的属性添加属性观察器(property observers),这样一来,当属性值改变时,类就会被通知到。可以为任何属性添加属性观察器,无论它原本被定义为存储型属性(stored property)还是计算型属性(computed property)。

重写

子类可以为继承来的实例方法,类方法,实例属性,或下标提供自己定制的实现。我们把这种行为叫重写。

如果要重写某个特性,你需要在重写定义的前面加上override关键字。这么做,你就表明了你是想提供一个重写版本,而非错误地提供了一个相同的定义。意外的重写行为可能会导致不可预知的错误,任何缺少override关键字的重写都会在编译时被诊断为错误。

override关键字会提醒 Swift 编译器去检查该类的超类(或其中一个父类)是否有匹配重写版本的声明。这个检查可以确保你的重写定义是正确的。

例子:

//定义一个基类(父类)
class Founder{
    var name = ""
    var money:Int?
    var company: String = ""
    var title: String{
        get{
            return "\(company) CEO"
        }
    }
    
    func say(){
        print("我叫\(name),是\(company)的创始人,我拥有\(money!)亿的财富!")
    }
}

//定义一个子类
class Heir:Founder{
    //重写属性观察器.
    override var name:String{
        didSet{
            print("\(name)")
        }
    }
    //重写只读属性
    override var title: String{
        return "\(company) 二代 CEO"
    }
    //重写方法
    override func say(){
        super.say()
        print("我叫\(name),是\(company)的下一代负责人,我拥有\(money!)亿的财富!")
    }
}
你可以在属性重写中为一个继承来的属性添加属性观察器。这样一来,当继承来的属性值发生改变时,你就会被通知到,无论那个属性原本是如何实现的.

注意:

1:你不可以为继承来的常量存储型属性或继承来的只读计算型属性添加属性观察器。这些属性的值是不可以被设置的,所以,为它们提供willSet或didSet实现是不恰当。此外还要注意,你不可以同时提供重写的setter和重写的属性观察器。如果你想观察属性值的变化,并且你已经为那个属性提供了定制的 setter,那么你在 setter 中就可以观察到任何值变化了。
 
2:上面 super.say()要明白: 只有拥有父类的类才拥有 super属性.在子类的实例化方法中使用super,super代表子类实例中引用父类类型初始化的部分,而在子类的类型方法中使用super时,super则表示父类的类型本身.在合适的地方,你可以通过使用super前缀来访问超类版本的方法,属性或下标脚本:
 
 1)在方法someMethod的重写实现中,可以通过super.someMethod()来调用超类版本的someMethod方法。
 2)在属性someProperty的 getter 或 setter 的重写实现中,可以通过super.someProperty来访问超类版本的someProperty属性。
 3)在下标脚本的重写实现中,可以通过super[someIndex]来访问超类版本中的相同下标脚本。
 

func testOne(){
    let father = Founder()
    father.name = "jack"
    father.company = "上帝集团"
    father.money = 1000
    father.say()
    
    let son = Heir()
    son.name = "jey"
    son.company = "上帝集团"
    son.money = 1000
    son.say()
}
执行结果:

 我叫jack,是上帝集团的创始人,我拥有1000亿的财富!
 jey
 我叫jey,是上帝集团的创始人,我拥有1000亿的财富!
 我叫jey,是上帝集团的下一代负责人,我拥有1000亿的财富!
 
 上面示例代码是继承的用法,需要注意几点:
 
 1:继承可以用于类而不能够用于结构体和枚举,继承也可以用于协议.
 2:Swift中类不允许出现多继承,比如class Heir:Founder, People{}的情况.
 3:父类的计算属性可以被子类重写,如果该计算属性在父类中是只读,则子类可以重写该属性,使其变成 只读或者可读可写属性,但是如果父类中是可读可写属性,则子类重写后必须是可读可写属性而不能是 只读属性.简单了解就是子类的属性读写权限必须大于等于父类.
 4:父类的方法可以被子类重写,函数前必须使用override关键字修饰.
 5:父类的下标方法也可以被子类重写,也需要使用override关键字修饰.

防止重写

可以通过把方法,属性或下标脚本标记为final来防止它们被重写,只需要在声明关键字前加上final特性即可。(例如:final var,final func,final class func, 以及final subscript

如果重写了final方法,属性或下标脚本,在编译时会报错。在类扩展中的方法,属性或下标脚本也可以在扩展的定义里标记为 final。

可以通过在关键字class前添加final特性(final class)来将整个类标记为 final 的,这样的类是不可被继承的,任何子类试图继承此类时,在编译时会报错。

class Founder{

    var name = ""
    var money:Int?
    var company: String = ""
    final var title: String{ //这里使用了final,子类将不能够重写.重写会报错
        get{
            return "\(company) CEO"
        }
    }
    
    func say(){
        print("我叫\(name),是\(company)的创始人,我拥有\(money!)亿的财富!")
    }
}

权限控制


给一段代码加上final就意味着编译器向你作出保证,这段代码不会再被修改;同时,这也意味着你认为这段代码已经完备并且没有再被进行继承或重写的必要,因此这往往会是一个需要深思熟虑的决定。


一般来说,不希望被继承和重写会有这几种情况:

1)类或者方法的功能确实已经完备了。

2)子类继承和修改是一件危险的事情。即在子类继承或重写某些方法后可能做一些破坏性的事情,导致子类或者父类部分也无法正常工作的情况。

3)为了父类中某些代码一定会被执行。有时候父类中有一些关键代码是在被继承重写后必须执行的 (比如状态配置,认证等等),否则将 导致运行时候的错误


性能考虑


使用final的另一个重要理由是可能带来的性能改善。因为编译器能够从final中获取额外的信息,因此可以对类或者方法调用进行额外的优化处理。但是这个优势在实际表现中可能带来的好 处其实就算与 Objective-C 的动态派发相比也十分有限,因此在项目还有其他方面可以优化 (一般 说会是算法或者图形相关的内容导致性能瓶颈) 的情况下,并不建议使用将类或者方法转换的方式来追求性能的提升。


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值