美文网首页
Swift属性绕脑细节,全在这里

Swift属性绕脑细节,全在这里

作者: Seer已被使用 | 来源:发表于2018-11-16 23:13 被阅读23次

    引言

      最近学习Swift,初看很简单。深入下来发现,其实里面有稍显复杂的细节需要记住。希望通过此文总结Swift中属性、属性重写、常量变量等特性在Swift继承机制中的要点,帮助自己记住,也帮助需要的朋友对知识点的记忆和理解不再混乱。

    摘要

      对于初学者而言,本文着重围绕Swift属性,从4个方面分析总结Swift属性的各种使用方法,以及属性、属性观察器、setter、getter在继承中的重写规则

    发车

    一、属性的不同特性的组合
      这里的特性一词指和属性相关的具有对立特性的4组性质,如下:
      1.层级性,对象层级和类层级。
      2.功能性,存储和计算。
      3.加载方式,有延迟加载和非延迟加载。
      4.附加操作,有set、get方法和willSet 、didSet观察器。
      (以上所列举的知识点Swift4.0 教程里有详细的讲解,本文只对细节方面的东西作出总结。)
      若对以上4点进行排列组合,理论上将得到足足16种确切类型的属性,对于新手来说,这将会很混乱。这也是我写本文的初衷。当然,实际上,并没有这么多啦,有些组合是天生不支持的。只是在初学过程中,我们对于Swift支持哪种和哪种搭配一开始是混乱的,接下来我们来理清这些东西。
      (一)、对象属性
        只有可变对象存储属性可以使用lazy
        只有可变存储型且非延迟属性可使用willSetdidSet属性观察器
        setget计算属性的专利,不需要考虑存储属性

        // 变存储属性
        var objProperty1:String = ""     
        let objProperty2:String = "" 
    
        // 变存储属性 + 观察器
        var objProperty3:String = ""{
               // 属性观察器并不是必须的!
               willSet{/* 操作newValue */}
               didSet{/* 操作oldValue */}
         }
    
        // 计算属性,只能用var
         var calProperty:Int{
               set{/* 操作newValue */}
               get{/* 返回计算的值 */}
         }
    

      (二)、类属性
        由staticclass修饰,我们用排除的思路来依依分析,首先,对于类属性,由于类没有自己的(显式)构造器,任何一个类属性(无论贫穷还是富贵,呸...无论是计算型还是存储型),因为没有构造器,所以必须在定义的时候设置默认值(可选类型除外)。因此,我们可以总结为staticclasslazy永远不可能放一起
        staticclass区别:
        1、存储型类属性只能用static修饰,且不能被重写
        2、计算型类属性可以用static也可以用class,只有class修饰的可以被子类重写

        // 变存储属性
        static var objProperty1:String = ""    
     
        // 常存储属性
        static let objProperty1:String = ""   
        
        // 变存储属性 + 观察器
        static var objProperty3:String = ""{
               // 属性观察器并不是必须的!
               willSet{/* 操作newValue */}
               didSet{/* 操作oldValue */}
         }
    
        // 计算属性,只能用var, static修饰不能被重写
        static var calProperty1:Int{
               set{/* 操作newValue */}
               get{/* 返回计算的值 */}
         }
    
        // 计算属性,class修饰能被重写
        class var calProperty2:Int{
               set{/* 操作newValue */}
               get{/* 返回计算的值 */}
         }
    

    二、关于重写
      (一)、类属性
        类属性有且只有"class+var+变量名+计算属性"一种情况可以被重写
      (二)、对象属性
        1、凡是let常量属性均不可重写
        2、可变存储属性和计算属性可以重写为计算属性
      (三)、你以为这么简单就总结完了?

    // 1、
    class var classProperty3:String{  // 父
            get{
                return "classProperty3父类get的返回值"
            }
            set{
                print("classProperty4 父类 set  newValue:\(newValue)")
            }
    }
    
    override class var classProperty3:String{  // 子
            get{
                return "classProperty3 子类 get"
            }
            
            set{
                print("classProperty3 子类 set newValue:\(newValue)")
            }
    }
    
    // 运行子类对象.classProperty3 = "newValue"
    // 输出: classProperty3 子类 set newValue:newValue
    
    // 2、
    class var classProperty4:String{   // 父
            set{
                print("classProperty4 父类 set  newValue:\(newValue)")
            }
            
            get{
                return "classProperty4父类get的返回值"
            }
     }
    
    override class var classProperty4:String{  // 子
            willSet{
                print("classProperty4 子类 willSet newValue:\(newValue)")
            }
            
            didSet{
                print("classProperty4 子类 didSet oldValue:\(oldValue)")
            }
    }
    // 运行:子类对象.classProperty4 = "newValue"
    // 输出:
    // classProperty4 子类 willSet newValue:newValue
    // classProperty4 父类 set newValue:newValue
    // classProperty4 子类 didSet oldValue: classProperty4父类get的返回值
    // didSet后的oldValue是调取的父类的get方法
    
    // 3、
    var objp2:String = "varObjp2"  // 父
    
    override var objp2: String{    // 子
            get{
                return "子类objp2 get"
            }
            
            set{
                print("子类objp2 set newValue:\(newValue)")
            }
     }
    // 运行:子类对象.objp2 = "newValue"
    // 输出:子类objp2 set newValue:newValue
    
    // 4、
    var objp31:String = "oldV31"{ // 父
            willSet{
                print("objp31 父类 WillSet newValue:\(newValue)")
            }
            
            didSet{
                print("objp31 父类 DidSet oldValue:\(oldValue)")
            }
     }
    
    override var objp31: String{ // 子
            
            set{
                print("objp31 子类 set newValue:\(newValue)")
            }
            
            get{
                return "objp31 子类 get"
            }
    }
    // 运行:子类对象.objp31 = "newValue"
    // 输出:objp31 子类 set newValue:newValue
    // 并不会调用父类的观察器
    
    // 5、
    var objp32:String = "oldV32"{ //父
            willSet{
                print("objp32 父类 WillSet newValue:\(newValue)")
            }
            
            didSet{
                print("objp32 父类 DidSet oldValue:\(oldValue)")
            }
    }
    
    override var objp32: String{ //子
            
            willSet{
                print("objp32 子类 willSet newValue:\(newValue)")
            }
            
            didSet{
                print("objp32 子类 didSet oldValue:\(oldValue)")
            }
     }
    // 运行:子类对象. objp32 = "newValue"
    // 输出:
    // objp32 子类 willSet newValue: newValue:newValue
    // objp32 父类 WillSet newValue:newValue
    // objp32 父类 DidSet oldValue:oldV32
    // objp32 子类 DidSet oldValue:oldV32
    
    // 6、
    var objp41:String{
            set{
                print("objp41 父类 set newValue:\(newValue)")
            }
            
            get{
                return "objp41父类get的返回值"
            }
    }
    
    override var objp41: String{
            willSet{
                print("objp41 子类 willSet newValue:\(newValue)")
            }
            
            didSet{
                print("objp41 子类 didSet oldValue:\(oldValue)")
            }
     }
    // 运行:子类对象.objp41 = "newValue"
    // 输出:
    // objp32 子类 willSet newValue: newValue:newValue
    // objp41 父类 set newValue:newValue
    // objp32 子类 DidSet oldValue:objp41父类get的返回值
    
    // 7、
    var objp42:String{ //父
            set{
                print("objp42 父类 set newValue:\(newValue)")
            }
            
            get{
                return "objp42父类get的返回值"
            }
    }
    
    override var objp42: String{ //子
            set{
                print("objp42 子类 set newValue:\(newValue)")
            }
            
            get{
                return "objp42 子类 get"
            }
    }
    // 运行:子类对象.objp42 = "newValue"
    // 输出:objp42 子类 set newValue:newValue
    

      (四)、有一开始就对这7种重写方式不晕头的吗?反正我是晕了
        通过做这七组对照试验,也算是终于把属性在Swift继承中的规则搞清楚了,折腾了好久(写上面的例子以及试验完又写这篇文章)也是真的挺伤神的,毕竟每个字句都是自己敲下来的纯手打。不过在写这一段话时,我也还是觉得值得的,通过这样一折腾,更好的掌握了Swift属性在继承特性中的机制,比起昨晚一开始看见就晕头的状态,现在也对这一部分的要点有了把握和信心~

    结语

      各位老铁如果发现文中的不足错误,欢迎在评论中指出。望海涵~
      另外,本文是原创文章,转载请附上原文地址,谢谢大家。

    相关文章

      网友评论

          本文标题:Swift属性绕脑细节,全在这里

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