首页 > 代码库 > Swift学习笔记十:属性

Swift学习笔记十:属性

1、存储属性

      1. 作为特定类或结构实例的一部分,存储属性存储着常量或者变量的值。存储属性可分为变量存储属性(关键字var描述)和常量存储属性(关键字let描述)。

struct student{
    let name = ""
    var score = 0
}
let a = student(name:"小笨狼",score:96)

          注意:
               ① 定义储存属性时,需要为每一个属性定义一个默认值。在初始化的时候,可以设置属性的初始值
               ② 对于结构当用let创建一个常量实例时(如let a),这个实例中的属性将不可改变,即使属性是变量属性(a中的score属性也不可改变)。这是因为结构是值类型。当一个值类型实例作为常量而存在,它的所有属性也作为常量而存在。但是这个特性对类并不适用,因为类是引用类型


      2. 懒惰储存属性
          懒惰存储属性是当它第一次被使用时才进行初值计算。通过在属性声明前加上@lazy来标识一个懒惰存储属性。
          当属性初始值因为外部原因,在实例初始化完成之前不能够确定时,就要定义成懒惰存储属性。当属性初始值需要复杂或高代价的设置,在它需要时才被赋值时,懒惰存储属性就派上用场了。

class student{
    let name = ""
    @lazy var score = 0
}
var a = student()   //这时候score还为被创建
a.score = 98        //score第一次使用时才会被创建
println(a.score)    //输出:98
          注意:
               ① 懒惰存储属性必须是变量属性(var定义的属性),因为它的初始值直到实例初始化完成之后才被检索。常量属性在实例初始化完成之前就应该被赋值,因此常量属性不能够被声明为懒惰存储属性。如果声明,编译器会报错

2. 计算属性

       1. 基本操作
          除了存储属性,类、结构和枚举能够定义计算属性。计算属性并不存储值,它提供getter和可选的setter来间接地获取和设置其它的属性和值。
struct XSize{
    var xOrigin:Float = 0
    var length:Float = 0
}
class test{
    var size = XSize()
    var center:Float{
    get{
        return size.xOrigin + size.length/2
    }       //get方法,获取值
    set(newSize){
        size.xOrigin = newSize - size.length/2
    }       //set方法,存储值
    }
}
          如上面例子所示,center并不存储值,只是提供getter和可选的setter来间接地获取和设置其它的属性和值。


     2.setter声明的简略写法
          如果计算属性的setter方法没有将被设置的值定义一个名称,将会默认地使用newValue这个名称来代替。

class test{
    var size = XSize()
    var center:Float{
    get{
        return size.xOrigin + size.length/2
    }       //get方法,获取值
    set{
        size.xOrigin = newValue - size.length/2
    }       //set方法,存储值
    }
}
     

     3. 只读计算属性
          只读计算属性只带有一个getter方法,通过点操作符,可以放回属性值,但是不能修改它的值。

class test{
    var size = XSize()
    var center:Float{
    get{
        return size.xOrigin + size.length/2
    }       //get方法,获取值
    }
}

          可以通过移除get关键字和它的大括号,简化只读计算属性的定义:
class test{
    var size = XSize()
    var center:Float{
    return size.xOrigin + size.length/2
    }       //get方法,获取值
}

          注意:
               ① 计算属性(包含只读计算属性)应该使用var关键字,因为它们的值并不是固定的。let关键字只被常量属性说使用。如果使用let定义,编译器将会报错
               ② 使用计算属性一定要声明类型,否则编译器会报错

3. 属性观察者
          属性观察者观察属性值的改变并对此做出响应。当设置属性的值时,属性观察者就被调用,即使当新值同原值相同时也会被调用。
          除了懒惰存储属性,你可以为任何存储属性加上属性观察者定义。另外,通过重写子类属性,也可以继承属性(存储或计算)加上属性观察者定义。属性重写在“重写”章节定义。

class student{
    var name:String = "abc"{
    willSet(newName){
        println("will set new:\(newName)")  //输出:will set new:小笨狼
    }
    didSet(oldName){
        println("did set new:\(name),old:\(oldName)")  //输出:did set new:小笨狼,old:abc
    }
    }
}
let a = student()
a.name = "小笨狼"

          注意:
               ① 对属性添加观察者必须声明属性类型,否则编译器报错
               ② willSet可以带一个newName的参数,如果不这样的话,这个参数就默认地被命名成newValue。
               ③ didSet也可以带一个oldName的参数,表示旧的属性,如果不带,这个参数默认命名为oldValue
               ④ 属性初始化时,willset和didSet并不会被调用。只有在初始化上下文之外,当设置属性值时才被调用
               ⑤ willSetdidSet每次设置属性值时都会被调用,即使是设置的值和原来值相同

4. 全局和局部变量
          以上所写的关于计算与观察属性值的特性同样适用于全局和局部变量。全局变量是在任何函数、方法、闭包、类型上下文外部定义的变量,而局部变量是在函数、方法、闭包中定义的变量。
          前面章节所遇到过的全局、局部变量都是存储变量。和存储属性一样,存储变量为特定类型提供存储空间并且可以被访问
          但是,你可以在全局或局部范围定义计算变量和存储变量观察者。计算变量并不存储值,只用来计算特定值,它的定义方式与计算属性一样。
     注意:
          全局常量和变量通常是延迟计算的,跟懒惰存储属性一样,但是不需要加上@lazy。而局部常量与变量不是延迟计算的。

5. 类型属性
          实例属性是特定类型实例的属性。当创建一个类型的实例时,这个实例有自己的属性值的集合,这将它与其它实例区分开来。
          也可以定义属于类型本身的属性,即使创建再多的这个类的实例,这个属性也不属于任何一个,它只属于类型本身,这样的属性就称为类型属性。

    1. 类型属性定义
          对值类型而言,定义类型属性使用static关键字,而定义类类型的类型属性使用class关键字。下面的例子展示了存储和计算类型属性的用法:

struct Student{
    static var name = ""
    static var score:Int{
    return 0
    }
}
class School{
    class var name:String{
    return "NB小学"
    }
}

          注意:
               上面的例子是针对只读计算类型属性而言的,不过你也可以像计算实例属性一样定义可读可写的计算类型属性
     2. 查询与设置类型属性
          像实例属性一样,类型属性通过点操作符来查询与设置。但是类型属性的查询与设置是针对类型而言的,并不是针对类型的实例。例如:

Student.name = "小笨狼"
println(Student.name)   //输出:小笨狼
println(School.name)    //输出:NB小学
          重点:
               通过类的名称来访问属性