属性用于描述特定类、结构或者枚举的值。在Swift中属性可以分为存储属性、计算属性和类属性三种。
1.存储属性
存储属性就是存储特定类的一个常量或者变量。常量存储的属性使用‘let’关键字定义,变量存储的属性使用‘var’关键字定义。
struct PersonInfo {
let name:String
var age:Int
}
var person = PersonInfo(name: "小明", age: 18)
// 打印person的name属性
print(person.name)
// 定义是var的病例才可以对里面的变量进行修改
person.age = 20
因为结构体时值类型,所以如果创建一个结构实例person,并将其赋给一个常量(let),那么即使这个结构中的属性是变量属性也不可以被改变。
当一个值类型实例作为常量二存在,它的所有属性也将会作为常量而存在。而这个特性对类并不适用,因为类是引用类型。如果将引用类型的实例赋值给常量,依然能够改变实例的变量属性。
![](https://img.haomeiwen.com/i2188748/bd388bf157770230.jpeg)
2.懒存储属性
懒存储,就是我们所说的懒加载,是指当被第一次调用的时候才会计算其初值的属性,在属性声明的前面加上 lazy 就可以了。
当属性初始值因为外部原因,在实例初始化完成之前不能确定,或者当属性初始值需要复杂、大量的计算时,就可以使用懒存储属性。
必须将懒存储属性声明成变量,因为属性的值在实例构造完成之前可能无法得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成懒存储属性。
3.计算属性
计算属性不存储值,而是提供了一个getter和setter来分别进行获取和设置其他属性的值。
class Person {
var length:Int = 10
var age:Int {
get {
return length * 2
}
set {
length = newValue / 2
}
}
// 只读计算属性
var height:Int{
get {
return length * 4
}
}
// 只读可以直接省略 get
var height2:Int{
return length * 4
}
}
var person = Person()
person.height
计算属性必须使用 var 关键字定义,包括只读计算属性,因为他们的值是不固定的,let关键字只用来声明常量存储的属性,便是初始化以后再也无法修改的值。
4.属性观察器
属性观察器可以来监控和响应初始化的属性值变化,当属性的值发生改变的时候,可以调用事先写好的代码额外执行一些操作并对此作出响应。
属性观察器的一些特点:
(1)给属性添加观察器必须要声明清楚属性类型,否则编译器报错。
(2)willSet可以带一个newName的参数,没有的话,该参数默认命名为newValue。
(3)didSet可以带一个oldName的参数,表示旧的属性,不带的话默认命名为oldValue。
(4)属性初始化时,willSet和didSet不会调用。只有在初始化上下文之外,当设置属性值时才会调用。另外,在didSet的实现体内给属性赋值,也不会再次调用属性的。
(5)即使是设置的值和原来值相同,willSet和didSet也会被调用。
class Person {
var name:String?
var age:Int = 10 {
// 在age属性发生变化之前做点什么
willSet {
print("将要设置年龄的值为\(newValue)")
}
// 在age属性发生变化之后,更新一下name这个属性
didSet {
if age < 10 {
name = "lucy"
} else {
name = "lily"
}
print("\(name)的年龄从\(oldValue)改为\(age)")
}
}
}
let person = Person()
person.age = 5
person.age = 20
![](https://img.haomeiwen.com/i2188748/f3cb60de81378ecf.png)
如果在didSet观察器里为属性赋值,这个值会替换观察器之前设置的值
5.类型属性
假设一个学生类,它有三个属性,生活费、学费、姓名,其中生活费和姓名每个学生实例都可以不同,但是学费属性对于学生来说是相同的,学费与个体无关,不需要实例化就可以使用,这种属性就可以被称为类属性。使用static关键字来定义,结构体、枚举和类都可以定义类型属性,下面我们就写几个事例:
结构体的属性:
struct Student {
var livingConst:Double = 0.0
var owner:String = ""
static var tuition:Double = 4500
static var tuitionProp:Double {
return tuition + 100
}
var totalCost:Double {
return Student.tuition + livingConst
}
}
// 访问静态属性
print(Student.tuitionProp)
var aStudent = Student()
// 访问实例属性
aStudent.livingConst = 1_000
// 访问实例属性
print(aStudent.totalCost)
枚举类型属性:
enum Student {
case Java
case PHP
case iOS
static var tuition:Double = 4500
static var tuitionProp:Double {
return tuition + 100
}
var instanceProp:Double {
switch self {
case Java:
Student.tuition = 15000
case PHP :
Student.tuition = 16000
default:
Student.tuition = 17000
}
return Student.tuition + 1_000
}
}
// 访问静态属性
print(Student.tuitionProp)
var aStudent = Student.iOS
// 访问实例属性
print(aStudent.instanceProp)
类类型属性:
class Student {
var livingConst:Double = 0.0
var name:String = ""
static var tuition:Double = 4500
static var tuitionProp:Double {
return tuition
}
var totalCost:Double {
return Student.tuition + livingConst
}
}
// 访问静态属性
print(Student.tuitionProp)
var aStudent = Student()
// 访问实例属性
aStudent.livingConst = 1_000
// 访问实例属性
print(aStudent.totalCost)
跟实例的存储属性不同,类型的存储属性必须指定默认值。因为类型本身无法再初始化过程中使用构造器给类型属性赋值
网友评论