美文网首页
Swift3.x - 类和结构体

Swift3.x - 类和结构体

作者: ibabyblue | 来源:发表于2017-03-21 11:18 被阅读22次

    类的介绍和定义

    • Swift也是一门面向对象的开发语言。
    • 面向对象的基础就是类,类产生对象。
    • Swift如何定义类:
      • class关键字定义类
      class 类名: SuperClass {
            //定义属性和方法
      

    }

    * 使用注意:
    * 定义类的时候,可以没有父类,那么该类就是根类
    * 通常情况下定义定义类时,继承自NSObject
    
    **如何定义类的属性**
    * Swift中类的属性有多种:
    * 存储属性:存储实例的常量和变量
    * 计算属性:通过某种方式计算出来的属性
    * 类属性:与整个类相关的属性
    * 存储属性
      ```
      class person: NSObject{
          //存储属性
          var age = 0
          var name: String?
      }
    
      let child = person()
      child.age = 18
      child.name = "小明"
    
      if let name = child.name {
          print("\(name)今年\(child.age)了")
      }
      //结果:小明今年18了
      ```
    * 计算属性
    在类中声明的计算属性,这个属性可以由类中定义的函数来完成,但是苹果官方并不见这种实现方式,因为计算属性的方式更加简单明了,下面就来实现以下某个人的在某段时间内完成跑步的平均时速。
    

    class person: NSObject{

      var time = 2
      var startSpeed = 10.0
      var hightSpeed = 20.0
      var endSpeed = 5.0
    
       //推荐
       var averageSpeed: Double {
           return (startSpeed + hightSpeed + endSpeed) * 0.5
       }
       //不推荐
       func averageSpeedFunction() -> Double {
          return (startSpeed + hightSpeed + endSpeed) * 0.5
      }
    

    }

    let child = person()
    child.averageSpeedFunction()
    child.averageSpeed

    * 类属性
    类属性是和整个类相关的属性,而且是通过类名来访问。常见于单例!
    

    class person: NSObject{

      //定义某个人有书籍的数量
      static var book = 0
    

    }

    person.book = 2
    //结果:2

    **类的构造函数**
    * 构造函数
      * 构造函数类似于OC中的初始化方法:init方法
      * 默认情况下创建某个类时,必然会调用一个构造函数
      * 即便开发者没有构建构造函数,编译器也会提供默认的构造函数
      * 如果继承自NSObject可以对父类的构造函数进行重写
    * 构造函数的基本使用
      * 类的属性必须有值
      * 如未在定义时初始化值,可以在构造函数中赋值,通过传递参数,初始化类对象。
          ```
          class person: NSObject{
      
              var name: String?
              var height = 0.0
              //重写父类的构造方法
              //如果重写父类的构造方法,在实例化此类时,Xcode会提示这个方法,如果未重写,Xcode只会提示,我们自定义的构造方法!
              override init(){
                  super.init()
              }
              //自定义构造方法
              init(name: String, height: Double) {
                  self.name = name
                  self.height = height
              }
      
          }
    
          let child = person(name: "小明", height: 1.88)
          child.name
          child.height
          //结果:小明 1.88
          ```
      * 通过字典参数实例化类对象
        ```
          class person: NSObject{
      
          var name: String?
          var height = 0.0
          //重写父类的构造方法
          override init(){
               super.init()
          }
           //自定义构造方法
          init(name: String, height: Double) {
               self.name = name
               self.height = height
          }
      
          init(dict: [String : AnyObject]) {
                 //此种写法会报错,因为从字典中取出的值为AnyObject?可选类型,直接赋值会报错!
                 //self.name = dict["name"]
                 //self.height = dict["height"]
    
                 //解决方法1:
                 //as? 转换符 将as?左侧的类型转换成as?右侧的类型的可选类型
                 name = dict["name"] as? String
                 //as! 转换符 将as!左侧的类型转换成as! 右侧的类型的可选类型
                 height = dict["height"] as! Double
                 //但是此种写法同时有带来了新的问题,强制解包是很危险的操作,会造成程序crash
                  
                 //解决方法2:
                 name = dict["name"] as? String
                 //可选绑定
                 if let tempHeight = dict["height"] as? Double {
                        height = tempHeight
                 }
           }
          }
          let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject])
        ```
        利用KVC实现构造函数实现
        ```
            class person: NSObject{
      
            var name: String?
            var height = 0.0
            //重写父类的构造方法
            override init(){
                super.init()
            }
            //自定义构造方法
            init(name: String, height: Double) {
                self.name = name
                self.height = height
            }
            //KVC
            init(dict: [String : AnyObject]) {
                super.init()
                setValuesForKeys(dict)
            }
            //防止传入的字典存在未知的键值->报错
            override func setValue(_ value: Any?, forUndefinedKey key: String) {}
        }
        let child = person(dict: ["name":"小明" as AnyObject, "height": 1.90 as AnyObject, "weight": 100 as AnyObject])
        child.name
        child.height
        //结果:小明 1.9
        ```
    
    **类的属性监听器**
    * 在OC中我们可以重写set方法来监听属性的改变
    * Swift中可以通过属性观察者来监听和响应属性的改变
    * 通常监听存储属性和类属性
    * 通过设置以下方法来定义观察者
      * willSet:将在属性值即将改变时调用
      * didSet:将在属性值改变后调用
    
      class person: NSObject{
    
      var name: String?{
          willSet{
              print("\(name)")
          }
        
          didSet{
              print("\(name)")
          }
      }
    

    }
    let child = person()
    child.name = "小明"

    
    **结构体的介绍和定义**
    结构体与类存在很多共同点:
    * 定义属性用于存储值
    * 定义方法用于提供功能
    * 定义下标操作使得可以通过下标语法来访问实例所包含的值
    * 定义构造器用于生成初始化值
    * 通过扩展以增加默认实现的功能
    * 实现协议以提供某种标准功能
    
    * Swift中如何定义结构体:
      * struct关键字定义结构体
    

    struct 结构体名{
    //结构体属性or方法
    }

    
    **结构体实例化**
    结构体实例化和类实例化非常相似:
    

    struct SomeStruct{
    //结构体属性or方法
    var width = 0
    var height = 0
    }
    //实例化结构体
    var someStruct = SomeStruct()

    在Swift中,结构体可以直接修改结构体的子属性的值,这点是与OC不同之处!
    

    import UIKit

    struct SomeStruct{
    //结构体属性or方法
    var width = 0
    var height = 0
    }

    var someStruct = SomeStruct()
    someStruct.height = 100
    someStruct.height
    //结果:someStruct.height值为100

    **结构体的逐一构造器**
    结构体存在逐一构造器,而类中默认是不存在的!我们可以自定义构造函数来完成逐一构造器,上述类的自定义构造方法其实就是自定义的逐一构造器方法!
    

    struct SomeStruct{
    //结构体属性or方法
    var width = 0
    var height = 0
    }

    var someStruct = SomeStruct(width: 66, height: 88)
    someStruct.height
    //结果:88
    someStruct.width
    //结果:66

    **结构体与类之间的选择**
    
    �结构体总是通过值传递(值类型),类总是通过引用传递(引用类型)!
    按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
    * 该数据结构的主要目的是用来封装少量相关简单数据值。
    * 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用。
    * 该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用。
    * 该数据结构不需要去继承另一个既有类型的属性或者行为。
    
    ######注意:
    在Swift中字符串、数组、字典均为结构体的形式实现(OC中均为类的形式实现)。拷贝行为看起来似乎总会发生。然而,Swift 在幕后只在绝对必要时才执行实际的拷贝。Swift 管理所有的值拷贝以确保性能最优化,所以你没必要去回避赋值来保证性能最优化。
    
    Zeb
    参考地址:https://github.com/numbbbbb/the-swift-programming-language-in-chinese

    相关文章

      网友评论

          本文标题:Swift3.x - 类和结构体

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