免费开源的iOS开发学习平台

Swift:11 属性

类似于Objective-C中的类成员变量和属性,在Swift中,也有属性的概念。类的实例和类型本身都可以有属性,我们称之为实例属性和类型属性。属性又分为存储属性和计算属性两种,其中,类、结构和枚举都提供了计算属性,而只有类和结构体有存储属性。

存储属性

存储属性是类和结构体中用来存储常量和变量数据的属性。对于常量类型的存储属性,只能在属性初始化的时候赋值一次,就不可以再修改了。通过前面的结构体章节介绍,我们可知,结构体是值类型的,所以,如果一个结构体是一个常量的话,那么他的变量存储属性也只能赋值一次。而类是引用类型,没有这个限制。

struct size {
    var width:Int
    let height:Int
}

var s_var = size(width: 10, height: 20)
s_var.width = 30
//s_var.height = 40,无法编译,常量属性,不能被改变

let s_constant = size(width: 50, height: 60)
//d_var.width = 60,无法编译,常量结构体所有属性只能被初始化一次

计算属性

除存储属性外,类、结构体和枚举还可以定义计算属性,计算属性不直接存储值,而是提供一个 getter 选择器来获取值,一个可选的 setter 设置器来间接设置其他属性或变量的值。

struct rect {
    var width:Int
    let height:Int
    var circumference:Int{
        get{
            return 2*(width+height)
        }
        set(circu){
            width = circu/2 - height
        }
    }
}

var r = rect(width: 20, height: 10)

print("现在的周长是:\(r.circumference)")
//打印结果:现在的周长是:60
r.circumference = 50

print("更改后宽度是:\(r.width),周长是\(r.circumference)")
//打印结果:更改后宽度是:15,周长是50

如果计算属性的setter没有为新设置的值定义名称,使用默认的名称newValue。

    var circumference:Int{
        get{
            return 2*(width+height)
        }
        set{
            width = newValue/2 - height
        }
    }

只有getter没有setter的计算属性被称为只读计算属性(read-only computed properties)。只读计算属性始终返回一个值,并且可以通过点语法访问,但是不可以设置值。同时,get关键字可以直接省略。

struct rect {
    var width:Int
    let height:Int
    var area:Int{
            return width*height
    }
}

var r = rect(width: 20, height: 10)

print("现在的面积是:\(r.area)")
//现在的面积是:200

属性监视器

属性监视器是用来监视和响应属性值的改变,每次当属性值被设置的时候,属性监视器就会自动被调用。

可以为存储属性添加属性监视器,也可以在子类中通过覆盖属性的方式来给任何继承属性(存储属性和计算属性)来添加属性监视器。不需要为未覆盖过的计算属性定义属性监视器,因为完全可以通过setter来直接监视和响应计算属性的值的变化。

有两种监视器(willSet和didSet),可以选择全部或选任意其中一个,其中willSet在值设置前调用,didSet在新的值设置后立即调用。

willSet和didSet都可以设置一个常量形参来传递新、旧属性值。常量形参如果不设置,则使用默认的newValue、oldValue来传递。

struct gold{
    var num:Int{
        willSet{
            if newValue < 0{
                print("金币数低于0")
            }
        }
        didSet{
            if oldValue < num{
                print("金币数增加了:\((num-oldValue))")
            }
        }
    }
}

var my_gold = gold(num: 10)

my_gold.num = -2

my_gold.num = 0

my_gold.num = 30

代码执行结果如下图。

类型属性

类型属性,也可以叫做类属性,就是属于某个类型的属性,该类型下所有的实例都共享一份值。由于类型属性不依赖于该类型的任何实例,所以,类型属性在定义的时候必须要设置初始值。类型属性也有存储属性和计算属性两种。
在结构体和枚举中定义类型属性,使用static关键字,而在类中定义计算类型属性需要使用class关键字。类型属性使用点(.)运算符进行访问和设置。

class rectClass{
    static var width = 10
    class var proper:Int{
        return 10
    }
}

enum fruits{
    static var level = 3
    static var totals:Int{
        return 1
    }
}

struct rect{
    static var width = 10
    var height:Int
    
    var area:Int{
        return height * rect.width
    }
}

let rt = rect(height: 20)
print("rt的面积是:\(rt.area)")

rect.width = 30

print("rt的面积是:\(rt.area)")

let rt2 = rect(height: 10)

print("rt2的面积是:\(rt2.area)")

代码执行结果如下图。

示例代码

https://github.com/99ios/23.12