Swift中的属性

来源:互联网 发布:网络管理需求分析 编辑:程序博客网 时间:2024/06/05 22:46

  我们都知道,类是由属性和方法组成的,一般而言,属性主要是用来访问数据成员,而方法则是用来执行某些操作,比如说计算数据等等。在Objective-C中,属性主要是用来访问封装之后的数据成员,属性本身并不存储数据,数据是由数据成员来存储。但是在Swift中,属性承担了多种角色,它远比Objective-C中的属性更为强大。

  Swift中的属性可以分为存储属性和计算属性,其中存储属性就相当于Objective-C中的数据成员,主要是用来存储数据;而计算属性则可以通过计算其它属性的值来返回数据。下面我们来对它们做一个了解。

  1、存储属性

  Swift中的存储属性在形式上和普通的常量、变量并无不同。一般而言,属性在类被初始化的时候也要被初始化,否则就应该将其声明为可选类型。比如说:

class Student {    // 存储属性    var name: String?  // 声明为可选类型    var age: Int = 0  // 初始化为默认值    var sex: String = "Female"    var height: Double = 0.0}let p = Student()p.name = "LeBron James"p.age = 33p.sex = "Male"p.height = 2.03

  出于性能方面的考虑,有时候我们并不希望一个属性在被使用之前就被加载进内存,对于这种情况,我们可以使用关键字lazy来修饰:

class Student {    // 存储属性    var name: String?      // 延迟加载属性    lazy var dog: Dog = Dog()}struct Dog {    var name: String?    var age: Int = 0}// 实例化Student类let p = Student()p.name = "LeBron James"// 用到dog属性时,它才会被加载p.dog.name = "WangCai"

  假如我们没有用关键字lazy对Student类的dog属性进行修饰,那么当我们创建p实例的时候,它也会被实例化并被加载进内存。而使用lazy进行修饰之后,只有当我们用到它时,它才会被加载。另外,一定要注意,存储属性只适用于类和结构体这两种类型,并不适用于枚举

  2、计算属性

  计算属性本身并不会存储数据,而是从其它存储属性中计算得到数据。计算属性不仅可以用于类和结构体,还可以用于枚举。计算属性的格式为:

class(struct/enum) 类型名 {    存储属性    var 计算属性名: 属性数据类型 {        get {            return 计算完成后属性的值        }        set(新属性的值) {            // 其它代码        }    }}

  计算属性中提供一个get用来获取值,另外一个set用来设置其它属性或变量的值,其中set方法是可选的。另外,计算属性应该使用var来修饰。

  3、只读计算属性

  计算属性可以只有get访问器,而没有set访问器,像这种计算属性就是只读计算属性。只读计算属性还可以直接省略掉关键字get及其后面的花括号,直接返回计算后的值。只读计算属性在实际开发过程经常会用到,比如说设置导航控制器顶部状态栏的颜色:

// 重写父类状态栏管理的属性(这是一个只读的计算属性,可以省略get{},直接return就可以了)override var preferredStatusBarStyle: UIStatusBarStyle {    return .lightContent}

  4、属性监听器

  为了监听属性的变化,Swift中提供了属性监听器。属性监听器能够及时的监听存储属性的变化,即便是存储属性变化前后的值相同,它也能够监听到。但是,一定要注意,属性监听器并不能监听延迟存储属性(也就是用lazy修饰的存储属性)和常量属性的变化。

  属性监听器中有两个重要的关键字,分别是willSet和didSet。其中,willSet在属性监听器修改之前调用,而didSet在属性监听器修改之后调用。属性监听器的格式为:

class(struct) 类型名 {    其它存储属性    var 存储属性名: 存储属性的数据类型 = 初始化值 {        willSet(新值) {            // 代码        }        didSet(旧值) {            // 代码        }    }}

  注意,因为枚举不支持存储属性,所以属性监听器并不能在枚举中使用。下面,我们看一个具体的示例:

// 属性监听器class Person {    var age: Int = 0    var name: String = "Enrica" {        willSet(newValue) {            print("变量name的新值:\(newValue)")        }        didSet(oldValue) {            print("变量name的旧值:\(oldValue)")        }    }    var height: Double = 0}var p = Person()p.age = 10// 属性监听器一旦监听到name值的改变,就会调用willSet和didSet方法p.name = "LeBron"

  在上面的Person类中,存储属性name有一个默认的值“Enrica”,当我们使用p.name = "LeBron"重新给它赋值时,属性监听器立马就能监听到,然后做出相应的反映。另外,其实willSet和didSet后面小括号中的参数是可以省略的,系统会给它们分配一个默认的参数。比如说,上面的代码可以修改为:

// 属性监听器class Person {    var age: Int = 0    var name: String = "Enrica" {        willSet {            print("变量name的新值:\(newValue)")        }        didSet {            print("变量name的旧值:\(oldValue)")        }    }    var height: Double = 0}var p = Person()p.age = 10// 属性监听器一旦监听到name值的改变,就会调用willSet和didSet方法p.name = "LeBron"

  代码修改之后,运行的结果一毛一样。属性监听器看起来很麻烦,但是实际应用非常的广泛,所以一定要掌握。

原创粉丝点击