九、属性 Properties

1. Stored Properties

1.1 概述

classes, structures, and enumerations都可以定义 Stored Properties

Stored Properties 这是最简单的属性类型。例如:

    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

其中,length 为 let 型,一旦初始化后就不能改变。

 

1.2. 常量结构体实例的 Stored Properties (Stored Properties of Constant Structure Instances)

如果你创建了一个结构体的实例,并将它赋值为一个常量constant,那么即使这个结构体的属性为变量类型,你也不能修改这个属性的值。

    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

上面的代码中,rangeOfFourItems 的属性的值不能修改。

因为结构体是值类型,如果结构体为Constant,那么他的所有属性也会表现为Constant。

这与类是不同的,因为类是引用类型,如果一个类的实例为Constant,你仍然可以更改这个实例variable类型的属性的值。

 

1.3. 属性的懒加载 Lazy Stored Properties

Lazy Stored Properties 指 一个属性的初始化值不会马上计算出来,而是等到第一次使用时才计算。

当需要指明某个属性使用懒加载时,可以在定义时加上lazy 关键字。

注意:懒加载属性只有var类型的变量才能使用,因为它可能不会马上初始化。但是let类型不能使用懒加载,因为它定义时就必须有值。

    class DataImporter {//假设该类执行耗时的操作
        var fileName = "data.txt"
    }
    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

在上面的例子中,只有当importer属性第一次被使用 is first accessed ,DataImporter 实例才会被创建。

    println(manager.importer.fileName)
    // the DataImporter instance for the importer property has now been created
    // prints "data.txt"

 

2. Computed Properties

2.1 概述

classes, structures, and enumerations 都可以定义 computed properties

computed properties 并不真的存储一个值,相反的,它提供了一个getter和一个可选的setter,间接的检索和设置 retrieve and set 其他属性和值。

    struct Point {
        var x = 0.0, y = 0.0
    }
    struct Size {
        var width = 0.0, height = 0.0
    }
    struct Rect {
        var origin = Point() // Stored Property
        var size = Size()
        var center: Point { // Computed Property
            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)
    println("square.origin is now at (\(square.origin.x), \(square.origin.y))")
    // prints "square.origin is now at (10.0, 10.0)"

 

2.2 Read-Only Computed Properties

只有get方法而没有set方法的属性就是只读Computed Properties。

定义Read-Only Computed Properties时,可以省略get关键字

    struct Cuboid {
        var width = 0.0, height = 0.0, depth = 0.0
        var volume: Double { // 只读Computed Properties
          return width * height * depth
      }
    }
    let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
    println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
    // prints "the volume of fourByFiveByTwo is 40.0"

 

 3 属性监视器 Property Observers

Property Observers 监视某个属性值的改变,并作出响应。每当一个属性被赋值的时候(即使新值与原来的值相同),Property Observers会被调用。

任何你自己定义的stored properties(除开使用懒加载的属性)都可以添加属性监视器。另外,继承来的属性(whether stored or computed)也可以添加属性监视器,方法是在子类中覆盖父类的属性,然后添加Property Observers。(原话是:You can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass.)

注意:你没有必要给non-overridden computed properties添加监视器,因为你可以直接在它的set方法中对属性值的变化作出响应。

你可以添加以下的监视器:

  • willSet 属性值被存储之前调用。
    willSet的参数为新的那个值,类型为constant。你可以自己给这个参数命名,如果你不命名,那么你连挂号都可不写了,这时参数的默认名称为newValue
  • didSet  属性值被存储之后马上会调用。
    class StepCounter {
      var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
          println("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
          if totalSteps > oldValue {
          println("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

 

4. 全局变量和局部变量 Global and Local Variables

  • 全局变量 Global variables : 定义在function、method、closure和type context 之外的变量。
  • 局部变量 Local variables : 定义在  function, method, or closure context 之内的变量。

Computing Properties 和 Observing Properties 对全局变量和局部变量也可以使用。

  • 用于存储值的 stored variables 也可以添加 Observing Properties。
  • 用于计算的 Computed variables 的用法与 Computing Properties 类似。

注意:全局的常量和变量始终是懒加载的 computed lazily ,它的管理方式与 Lazy Stored Properties 类似。不同的是,全局变量/常量不用显示的添加 lazy 关键字。

而局部变量/常量 从来都不是 computed lazily。

 

5. Type Properties

5.1 概述

  • 实例属性 Instance properties :实例属性是某种类型的实例的属性,某种类型的多个实例互不干扰。比如某个类的对象的属性,就是实例属性。
  • 类型属性 Type properties :某种类型的属性就是类型属性。类型就是一个模子,可以用来创建实例。

你可以给某种类型本身定义属性(即类型属性),那么使用这种类型创建的实例都有这个属性的同一个副本(类似于C中的静态成员变量)。

  • 对于值类型 value types ,比如结构体和枚举,你可以定义 stored and computed type properties。
  • 对于类类型 class types,你只能定义 computed type properties。

 

5.2 Type Property 语法

对于 value types 类型的 Type Property 使用 static 关键字

对于 class types 类型的 Type Property 使用 class 关键字

    struct SomeStructure {
      static var storedTypeProperty = "Some value."
      static var computedTypeProperty: Int {
        // return an Int value here
      }
    }
    enum SomeEnumeration {
      static var storedTypeProperty = "Some value."
      static var computedTypeProperty: Int {
        // return an Int value here
      }
    }
    class SomeClass {
      class var computedTypeProperty: Int {
        // return an Int value here
      }
    }

上面的computedTypeProperty都是只读属性。

 

5.3 获取和设置类型属性 Querying and Setting Type Properties

使用点语法获取和设置 Type Properties,但是实际执行过程是在Type中,而不是在实例中。

    println(SomeClass.computedTypeProperty)// prints "42"
    println(SomeStructure.storedTypeProperty)// prints "Some value."
    SomeStructure.storedTypeProperty = "Another value."
    println(SomeStructure.storedTypeProperty)// prints "Another value."

例子:1到10声道

image: ../Art/staticPropertiesVUMeter_2x.png

    struct AudioChannel {
      static let thresholdLevel = 10 //最大值
      static var maxInputLevelForAllChannels = 0  
      var currentLevel: Int = 0 {//当前值
        didSet {
          if currentLevel > AudioChannel.thresholdLevel {
          // cap the new audio level to the threshold level
            currentLevel = AudioChannel.thresholdLevel
          }
          if currentLevel > AudioChannel.maxInputLevelForAllChannels {
            // store this as the new overall maximum input level
            AudioChannel.maxInputLevelForAllChannels = currentLevel
          }
        }
      }
    }


    var leftChannel = AudioChannel()
    var rightChannel = AudioChannel()

    leftChannel.currentLevel = 7
    println(leftChannel.currentLevel) // prints "7"
    println(AudioChannel.maxInputLevelForAllChannels) // prints "7"

    rightChannel.currentLevel = 11
    println(rightChannel.currentLevel) // prints "10"
    println(AudioChannel.maxInputLevelForAllChannels) // prints "10"

 

posted @ 2015-01-15 17:00  action爱生活  阅读(215)  评论(0编辑  收藏  举报