美文网首页
Swift(十五)属性

Swift(十五)属性

作者: 冰三尺 | 来源:发表于2016-11-01 19:31 被阅读19次
    星空

    计算属性和存储属性

    我们知道在OC中, 使用@ property声明的实例变量, 都会自动生成setter和getter方法, 但是在swift中, 属性分为计算属性和存储属性, 存储属性存储常量或变量作为实例的一部分,计算属性计算(而不是存储)一个值,就是setter和getter方法, 除存储属性外,类、结构体和枚举可以定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。

    延迟存储属性

    延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用lazy(xcode8)不是@lazy来标示一个延迟存储属性。类似于OC中的懒加载

    注意:必须将延迟存储属性声明成变量(使用var关键字),因为属性的值在实例构造完成之前可能无法得到(意思就是说, 延迟属性, 不需要在创建实例时赋初始值)。而常量(使用var)属性在构造过程完成之前必须要有初始值(如果你不给初始值, 编译器会根据类型推断, 自动分配),因此无法声明成延迟属性。

    class DataImporter { 
        /* 
        DataImporter 是一个将外部文件中的数据导入的类。 
        这个类的初始化会消耗不少时间。 
        */ 
        var fileName = "data.txt" 
        // 这是提供数据导入功能 
    } 
     
    class DataManager { 
        lazy var importer = DataImporter()  //延迟属性, 用到的时候才回去加载
        var data = String[]() 
        // 这是提供数据管理功能 
    } 
    

    计算属性

    //结构体
    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 { 
    //getter方法
        get { 
            let centerX = origin.x + (size.width / 2) 
            let centerY = origin.y + (size.height / 2) 
            return Point(x: centerX, y: centerY) 
        } 
    //setter方法, newCenter为setter方法的参数
        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  //getter方法, 获取center
    square.center = Point(x: 15.0, y: 15.0)  //setter方法, 设置新的center
    print("square.origin is now at (\\(square.origin.x), \\(square.origin.y))") 
    

    只读计算属性

    只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。(类比OC属性修饰readonly)
    注意:必须使用var关键字定义计算属性,包括只读计算属性,因为他们的值不是固定的。let关键字只用来声明常量属性,表示初始化后再也无法修改的值。

    struct Cuboid { 
        var width = 0.0, height = 0.0, depth = 0.0 
        var volume: Double { //只读计算属性的声明可以去掉get关键字和花括号:
    
        return width * height * depth 
        } 
    } 
    let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0) 
    print("the volume of fourByFiveByTwo is \\(fourByFiveByTwo.volume)") 
    

    属性监视器

    属性监视器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性监视器,甚至新的值和现在的值相同的时候也不例外. (类似于KVO, 但是比KVO方便多了)
    可以为属性添加如下的一个或全部监视器:

    willSet在设置新的值之前调用
    didSet在新的值被设置之后立即调用
    willSet监视器会将新的属性值作为固定参数传入,在willSet的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue表示。

    类似地,didSet监视器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。

    注意:willSet和didSet监视器在属性初始化过程中不会被调用,他们只会当属性的值在初始化之外的地方被设置时被调用。

    class StepCounter { 
        var totalSteps: Int = 0 { 
        willSet(newTotalSteps) {  //willSet监视器将表示新值的参数自定义为newTotalSteps
            print("About to set totalSteps to \\(newTotalSteps)") 
        } 
        didSet { 
            if totalSteps > oldValue  {  //didSet没有提供自定义名称,所以默认值oldValue表示旧值的参数名。
                print("Added \\(totalSteps - oldValue) steps") 
    //注意:如果在didSet监视器里为属性赋值,这个值会替换监视器之前设置的值。
            } 
        } 
        } 
    } 
    let stepCounter = StepCounter() 
    stepCounter.totalSteps = 200  //设置新值, 调用willSet
    // About to set totalSteps to 200 
    // Added 200 steps 
    stepCounter.totalSteps = 360 
    // About to set totalSteps to 360 
    // 
    

    类型属性

    实例的属性属于一个特定类型实例,每次类型实例化后都拥有自己的一套属性值,实例之间的属性相互独立。

    也可以为类型本身定义属性,不管类型有多少个实例,这些属性都只有唯一一份。这种属性就是类型属性。

    类型属性用于定义特定类型所有实例共享的数据,比如所有实例都能用的一个常量(就像 C 语言中的静态常量),或者所有实例都能访问的一个变量(就像 C 语言中的静态变量)。

    对于值类型(指结构体和枚举)可以定义存储型和计算型类型属性,对于类(class)则只能定义计算型类型属性。

    值类型的存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算属性一样定义成变量属性。

    注意:跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。

    //结构体
    struct SomeStructure {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            return 10
            // 这里返回一个 Int 值
        }
    }
    //枚举
    enum SomeEnumeration {
        static var storedTypeProperty = "Some value."
        static var computedTypeProperty: Int {
            // 这里返回一个 Int 值
            return 20
        }
    }
    //类
    class SomeClass {
    //这里在xcode8里, class改为static也可以(目前测试, 结果都是对的, 可能还有没有考虑到的情况)
        class var computedTypeProperty: Int {
            // 这里返回一个 Int 值
            return 30
        }
    }
    print(SomeStructure.computedTypeProperty) //10
    print(SomeStructure.computedTypeProperty) //20
    print(SomeClass.computedTypeProperty) //30
    
    

    相关文章

      网友评论

          本文标题:Swift(十五)属性

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