---页首---

Swift从入门到精通第七篇 - 属性 初识

属性(学习笔记)

环境Xcode 11.0 beta4 swift 5.1

  • 属性(Properties)

    • 属性是把值和特定的类、结构体、枚举关联在一起
    • 属性主要是分为存储属性(Stored Properties)和计算属性(Computed Properties)
    • 存储属性是用来存储实例的常量或者变量
    • 计算属性主要是用来计算值
    • 计算属性可以定义在类、结构体、枚举
    • 存储属性可以定义在类、结构体
  • 存储属性(Stored Properties)

    • 可以用var let修饰,后者一旦初始化就不可更改

      struct FixedLengthRange {
          var firstValue: Int
          let length: Int
      }
      var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
      // the range represents integer values 0, 1, and 2
      rangeOfThreeItems.firstValue = 6
      // the range now represents integer values 6, 7, and 8
      
    • 结构体实例常量的存储属性,即被let修饰,此时的存储属性被var修饰了不能更改,因为结构体是值类型,结构体变量的存储属性的内存是存储在结构体变量的内存中的

      let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
      // this range represents integer values 0, 1, 2, and 3
      rangeOfFourItems.firstValue = 6
      // this will report an error, even though firstValue is a variable property
      
    • 延迟存储属性(Lazy Stored Properties),用lazy来标识且只能申明为var,延迟存储属性是第一用到才赋值,而let修饰的属性要在初始化前就要有值

      // 以下示例代码类不是完整的类
      class DataImporter {
          /*
          DataImporter is a class to import data from an external file.
          The class is assumed to take a nontrivial amount of time to initialize.
          */
          var filename = "data.txt"
          // the DataImporter class would provide data importing functionality here
      }
      class DataManager {
          lazy var importer = DataImporter()
          var data = [String]()
          // the DataManager class would provide data management functionality here
      }
      let manager = DataManager()
      manager.data.append("Some data")
      manager.data.append("Some more data")
      // the DataImporter instance for the importer property has not yet been created
      print(manager.importer.filename)
      // the DataImporter instance for the importer property has now been created
      // Prints "data.txt"
      
    • 存储属性&实例变量,在OC中有两种方式存储值和类的实例对象,即属性和实例变量(即成员变量);Swift统一了这些概念,属性的所有信息(包括它的名称、类型和内存管理特性)都在类型定义的时候,作为类型的一部分定义在类型中

  • 计算属性(Computed Properties)

    • 计算属性不是真的用来存储值,而是提供gettersetter(可选)去获取和设置其它属性和值

      struct Point {
          var x = 0.0, y = 0.0
      }
      struct Size {
          var width = 0.0, height = 0.0
      }
      struct Rect {
          var origin = Point()
          var size = Size()
          var center: Point {
              get {
                  let centerX = origin.x + (size.width / 2)
                  let centerY = origin.y + (size.height / 2)
                  return Point(x: centerX, y: centerY)
              }
              set(newCenter) {
                  origin.x = newCenter.x - (size.width / 2)
                  origin.y = newCenter.y - (size.height / 2)
              }
          }
      }
      var square = Rect(origin: Point(x: 0.0, y: 0.0),
                        size: Size(width: 10.0, height: 10.0))
      let initialSquareCenter = square.center
      square.center = Point(x: 15.0, y: 15.0)
      print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
      // Prints "square.origin is now at (10.0, 10.0)"
      
    • 简写的setter声明(内部有一个默认的变量名newValue

      struct AlternativeRect {
          var origin = Point()
          var size = Size()
          var center: Point {
              get {
                  let centerX = origin.x + (size.width / 2)
                  let centerY = origin.y + (size.height / 2)
                  return Point(x: centerX, y: centerY)
              }
              set {
                  origin.x = newValue.x - (size.width / 2)
                  origin.y = newValue.y - (size.height / 2)
              }
          }
      }
      
    • 简写的getter声明(隐式返回即省略return)

      struct CompactRect {
          var origin = Point()
          var size = Size()
          var center: Point {
              get {
                  Point(x: origin.x + (size.width / 2),
                        y: origin.y + (size.height / 2))
              }
              set {
                  origin.x = newValue.x - (size.width / 2)
                  origin.y = newValue.y - (size.height / 2)
              }
          }
      }
      
    • 只读计算属性(Read-Only Computed Properties),只有getter,没有setter,可以用var修饰,getter也可以省略不写

      struct Cuboid {
          var width = 0.0, height = 0.0, depth = 0.0
          var volume: Double {
              return width * height * depth
          }
      }
      let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
      print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
      // Prints "the volume of fourByFiveByTwo is 40.0"
      
  • 属性观察器(Property Observers)

    • 观察和响应属性值的变化,即使设置的是相同的值也会触发;
    • 可以为任意的属性添加属性观察器,延迟存储属性除外
    • 可以在子类为任意继承属性(存储或计算属性)添加属性观察器
    • 非重写的计算属性不需要定义属性观察器,可以在setter中观察和响应
    • 可以在属性上添加willSet(在值存储前调用,自带一个常量参数newValuedidSet(新设置的值存储立即调用,自带一个常量参数oldValue
      class StepCounter {
          var totalSteps: Int = 0 {
              willSet(newTotalSteps) { // 不用默认的newValue,自定义一个参数
                  print("About to set totalSteps to \(newTotalSteps)")
              }
              didSet {
                  if totalSteps > oldValue  {
                      print("Added \(totalSteps - oldValue) steps")
                  }
              }
          }
      }
      let stepCounter = StepCounter()
      stepCounter.totalSteps = 200
      // About to set totalSteps to 200
      // Added 200 steps
      stepCounter.totalSteps = 360
      // About to set totalSteps to 360
      // Added 160 steps
      stepCounter.totalSteps = 896
      // About to set totalSteps to 896
      // Added 536 steps
      
    • 传递一个属性给一个in-out 参数,willSet didSet 都会被调用,这是因为in-out参数的copy-in copy-out 内存管理,在函数调用的最后总是会将值写加给属性
  • 全局和局部变量(Global and Local Variables)

    • 全局和局部变量都可以设置计算属性和属性观察器
    • 全局常量和变量总是延迟计算,类似延迟存储属性,但不需要lazy修饰
    • 局部常量和变量从不是延迟计算的
  • 类型属性(Type Properties)

    • 是线程安全的

    • 计算类型属性总是变量(同计算实例属性)和存储类型属性可以是变量或常量

    • static 关键字修饰,由class定义的类可以用class关键字标识类型属性,以便子类重写

      struct SomeStructure {
          static var storedTypeProperty = "Some value."
          static var computedTypeProperty: Int {
              return 1
          }
      }
      enum SomeEnumeration {
          static var storedTypeProperty = "Some value."
          static var computedTypeProperty: Int {
              return 6
          }
      }
      class SomeClass {
          static var storedTypeProperty = "Some value."
          static var computedTypeProperty: Int {
              return 27
          }
          class var overrideableComputedTypeProperty: Int {
              return 107
          }
      }
      // 以上示例代码是定义成只读属性,也可以定义成可读可写属性
      
    • 查询和设置类型属性,用 . 语法

      print(SomeStructure.storedTypeProperty)
      // Prints "Some value."
      SomeStructure.storedTypeProperty = "Another value."
      print(SomeStructure.storedTypeProperty)
      // Prints "Another value."
      print(SomeEnumeration.computedTypeProperty)
      // Prints "6"
      print(SomeClass.computedTypeProperty)
      // Prints "27"
      
posted @ 2019-09-09 15:07  20190311  阅读(162)  评论(0编辑  收藏  举报
---页脚---