美文网首页
Swift 4 Structure Properties Met

Swift 4 Structure Properties Met

作者: 艺术农 | 来源:发表于2018-06-14 13:39 被阅读24次

    Swift, in fact, includes four kinds of named types: structures, classes, enumerations and protocols.

    Swift包含四种自定义类型:结构体、类、枚举、协议。

    值类型(Value Type)和引用类型(Reference type)

    值类型是这样的一种类型,当在变量或常量赋值时,以及在函数中传递时,它的值会被拷贝,然后赋值给变量或常量,或传递给函数。Swift中所有的基本类型都是类型的值,背后是用结构体(structures)形式实现的。

    Swift中所有的结构体和枚举都是值类型

    与值类型相对,引用类型在赋值和函数传递时,都没有对值进行拷贝。而是使用一个指向同一存在实例的引用。

    改变值类型的变量值,只会改变该变量。

    改变引用类型的变量值,则会改变所有指向该变量的引用类型实例。

    Structure (结构体)

    • 结构体是值类型
    • 点语法访问成员变量
    • 结构体可以包含变量(属性)和函数(方法)
    • 结构体可以和协议一起使用

    Properties (属性)

    struct Car {
      let make: String
      let color: String
    }
    
    • 存储属性(Stored Properties)
      在内存中开辟空间存储实例的属性值。

    给存储属性添加默认值:

    struct Contact {
      var fullName: String
      let emailAddress: String
      var type = "Friend"
    }
    
    • 计算属性(computed Properties)
      在内存中不开辟存储空间,只在我们每次访问其时做一些计算任务。

    给计算属性添加getter和setter方法:

    var diagonal: Int {
      // 1
      get {
        // 2
        let result = (height * height + width * width).squareRoot().rounded()
        return Int(result)
      }
      set {
        // 3
        let ratioWidth = 16.0
        let ratioHeight = 9.0
        // 4
        let ratioDiagonal =
          (ratioWidth * ratioWidth + ratioHeight * ratioHeight).squareRoot()
        height = Double(newValue) * ratioHeight / ratioDiagonal
        width = height * ratioWidth / ratioHeight
      }
    }
    

    类型属性(Type properties)

    类似于静态成员变量,只是这里是用在结构体中。可以通过结构体名直接放问。

    struct Level {
      static var highestLevel = 1
      let id: Int
      var boss: String
      var unlocked: Bool
    }
    let highestLevel = Level.highestLevel // 1
    

    属性观察(Property observers)

    struct Level {
      static var highestLevel = 1
      let id: Int
      var boss: String
      var unlocked: Bool {
        didSet {
          if unlocked && id > Level.highestLevel {
            Level.highestLevel = id
          }
        }
      }
    }
    
    • Swift使用willset的didset方法来观察属性值的变化,不过值得注意的是,属性观察只能够被用在存储属性上,计算属性是无法使用的,很好理解为什么。因为,如果你想在计算属性上观察,直接在setter方法中操作即可,根本不需要属性观察的相关方法。

    • 与此同时,我们要记住,属性观察的方法只在属性的值发生变化时才被调用,也就是说初始化值不会调用属性观察,只有变量才能进行属性观察,常量是不可以的,因为常量只在初始化时候复制,而初始化时不会调用属性观察的相关方法的。

    • 获取setter方法新值newValue,旧值用oldValue。

    懒加载(Lazy properties)

    If you have a property that might take some time to calculate, you don’t want to slow things down until you actually need the property. Say hello to the lazy stored property. This could be useful for such things as downloading a user’s profile picture or making a serious calculation.

    如果某些属性需要我们花费时间去计算,同时,我们又不想浪费时间去等待,直至我们真正需要使用这个属性时。我们需要用到lazy properties.

    struct Circle {
      lazy var pi = {
        return ((4.0 * atan(1.0 / 5.0)) - atan(1.0 / 239.0)) * 4.0
      }()
      var radius = 0.0
      var circumference: Double {
        mutating get {
          return pi * radius * 2
        }
      }
      init(radius: Double) {
        self.radius = radius
      }
    }
    
    var circle = Circle(radius: 5) // got a circle, pi has not been run
    
    let circumference = circle.circumference // 31.42
    // also, pi now has a value
    

    上面的代码中,我们打算自己计算π的值。但是只有在真正用到π的值时我们才进行计算,这就是lazy properties。

    • lazy properties必须用var来修饰。
    • lazy var pi = { return ...}(),这段代码我们直接定义闭包接着直接调用。
    • mutating get {return pi * radius * 2 },为何这里使用mutating来修饰呢,因为返回值我们用到了pi,而使用pi的值时会修改结构体内部pi的值,所以要标记为mutating。

    Methods(方法)

    方法和函数有什么区别,其实方法就是放在结构体内部的函数而已。

    • 何时需要使用setter呢?


      img61.png

      总结下,当需要大量的计算或者从数据库读取值时,计算属性就不能够满足我们的需求,最好使用方法来替代。其他简单的情况都是使用计算属性。

    Initializers in structures(结构体中的构造方法)

    • Swift默认为结构体创造了一个为所有成员变量初始化值的构造方法。
    • 当我们自定义构造方法时,系统默认提供的构造方法会无效。
    • 通过extension扩展的构造方法,不会使远结构体的默认构造方法失效。

    mutating methods

    mutating修饰一个方法时,表示标记这个方法会改变结构体的值。因为结构体是值类型,每次操作都是做复制操作。如果其中一个方法改变了属性的值,那么源结构体和拷贝的结构体将不再相等。

    类型方法(Type methods)

    类型方法和 类型属性一样都是使用static关键字来修饰。

    struct Math {
      // 1
      static func factorial(of number: Int) -> Int {
        // 2
        return (1...number).reduce(1, *)
      }
    }
    // 3
    Math.factorial(of: 6) // 720
    

    You might have custom calculations for things such as factorial. Instead of having a bunch of free-standing functions, you can group related functions together as type methods in a structure. The structure is said to act as a namespace.

    您可以对诸如阶乘之类的东西进行自定义计算。您可以将相关函数分组为结构中的类型方法,而不是拥有一组独立的函数。该结构被称为命名空间

    结构体扩展(extensions)

    通过扩展,我们可以为已有的结构体添加方法、构造函数、计算属性,但是不能添加存储属性。

    下面的代码我们使用extension关键字对Math结构体进行了扩展。

    extension Math {
      static func primeFactors(of value: Int) -> [Int] {
        // 1
        var remainingValue = value
        // 2
        var testFactor = 2
        var primes: [Int] = []
        // 3
        while testFactor * testFactor <= remainingValue {
          if remainingValue % testFactor == 0 {
            primes.append(testFactor)
            remainingValue /= testFactor
          }
          else {
            testFactor += 1
          }
        }
        if remainingValue > 1 {
          primes.append(remainingValue)
        }
        return primes
      }
    }
    

    相关文章

      网友评论

          本文标题:Swift 4 Structure Properties Met

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