Swift中的属性

  我们都知道,类是由属性和方法组成的,一般而言,属性主要是用来访问数据成员,而方法则是用来执行某些操作,比如说计算数据等等。在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 = 33
p.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"

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值