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