zoukankan      html  css  js  c++  java
  • 九、属性 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( 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( 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"
  • 相关阅读:
    习题解答chapter09
    习题解答chapter08
    习题解答chapter07
    银行账户实验-1.2
    银行账户实验-1.1
    银行账户实验-1.0
    习题解答chapter06
    习题解答chapter05
    习题解答chapter04
    习题解答chapter03
  • 原文地址:https://www.cnblogs.com/actionke/p/4226753.html
Copyright © 2011-2022 走看看