第十章 属性
结构体,类和枚举中与值相关联的东西就叫做该结构体,类或枚举的属性,属性一般都是该结构体,类或枚举的常量或/和变量。属性又可以分为存储属性
和计算属性
。
存储属性可以由结构体和类提供,存储属性其实就是存储常量或变量作为实例的一部分。
而计算属性可以由结构体,类和枚举提供。计算属性并不是用来存储属性的,而是用来提供一个getter
和一个可选的setter?
来间接获取或重新设置其他属性或值。
除此之外可以定义一个属性观察器(property observer
)来监视属性值的变化。以此来对某个自定义的操作进行响应。属性观察器可以被添加到我们定义的存储属性里面,也可以被添加到一个从父类继承的子类属性里。
1. Stored Property (存储属性)
存储属性最简单的形式来说,就是存储在一个特定的结构体
或类
的实例里面的一个变量或常量,存储属性也可以是一个常量存储属性
(用let引出介绍)或一个变量存储属性
(用var引出介绍)。也可以给结构体或类的存储属性一个默认值。 可以在存储属性初始化的时候设置或修改当前的初始值。
struct FixedLengthRange {
// 结构体变量存储属性的类型注释
var firstValue: Int
// 结构体常量存储属性的类型注释
let length: Int
}
// 初始化,第一个值是0,长度是3。那么这个FixedLengthRange就是0,1,2
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 重新分配第一个值
rangeOfThreeItems.firstValue = 6
1.1 Stored Properties of Constant Structure Instance (常量结构体实例的存储属性)
如果我们创建了一个结构体的实例并且给给他赋值了一个常量,那么我们就无法修改这个实例的属性了,也就是说常量实例的属性是修改的,即使给该常量的实例属性重新分配一个值也是不可以的,这样将会出现报错(Cannot assign to property: 'rangeOfThreeItems' is a 'let' constant
)
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
// 结构体的实例 - 结构体的常量存储属性
let rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 常量不可以修改或重新分配另一个值
rangeOfThreeItems.firstValue = 6
FixedLengthRange(firstValue: 0, length: 3)它是结构体初始化属性值操作,对于常量实例rangeOfThreeItems来说它是一个值类型。
1.2 Lazy Stored Property (延迟存储属性)
延迟存储属性其实就是说这个存储属性,在第一次被调用的时候才开始计算初始化该结构体或类的属性值。我们可以用lazy
修饰符写在变量前面来指明这是一个延迟存储属性。下面这个例子会详细介绍。
class DataImporter {
// DataImporter是一个数据导入器的类,
// 它导入的数据来自于一个叫data.txt的文件
var filename = "data.txt"
}
// 不调用DataManager类
class DataManager {
// 也就不会执行该延迟存储属性的初始化值的操作
lazy var importer = DataImporter()
// 这个DataManager类中的变量String类型的data进行空白处理
// 该变量data是一个String类型的数组。
var data = [String]()
}
// 调用DataManager类 - 也将会执行延迟存储属性操作
let manager = DataManager()
// 给变量data数组元素的最后面添加Some data
manager.data.append("Some data")
// 给变量data数组元素Some data后面添加Some more data
manager.data.append("Some more data")
// 只是输出类DataManager中的一个存储属性
print(manager.data)
// 输出:[Some data,Some more data]
// 输出类的实例(实例化的类就会包含属性值)
// manager.importer.filename其实就是用数据导入器把这个数组导入进这个叫data.txt文件里。
// manager(实例名)importer(类的延迟存储属性)filename(类的属性)
print(manager.importer.filename)
// 输出:[Some data,Some more data]
print(manager.data)
和print(manager.importer.filename)
虽然输出都是一样的,但是区别在于print(manager.data)只是输出了实例化后的DataManager中的data属性。而print(manager.importer.filename)既要调用实例化后的DataManager中的延迟属性importer,再启动第一次数据的初始化和导入。