延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用@lazy
来标示一个延迟存储属性。
注意:
必须将延迟存储属性声明成变量(使用var
关键字),因为属性的值在实例构造完成之前可能无法得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。
延迟属性很有用,当属性的值依赖于在实例的构造过程结束前无法知道具体值的外部因素时,或者当属性的值需要复杂或大量计算时,可以只在需要的时候来计算它。
下面的例子使用了延迟存储属性来避免复杂类的不必要的初始化。例子中定义了DataImporter
和DataManager
两个类,下面是部分代码:
class DataImporter {
/*
DataImporter 是一个将外部文件中的数据导入的类。
这个类的初始化会消耗不少时间。
*/
var fileName = "data.txt"
// 这是提供数据导入功能
}
class DataManager {
@lazy var importer = DataImporter()
var data = String[]()
// 这是提供数据管理功能
}
let manager = DataManager()
manager.data += "Some data"
manager.data += "Some more data"
// DataImporter 实例的 importer 属性还没有被创建
DataManager
类包含一个名为data
的存储属性,初始值是一个空的字符串(String
)数组。虽然没有写出全部代码,DataManager
类的目的是管理和提供对这个字符串数组的访问。
DataManager
的一个功能是从文件导入数据,该功能由DataImporter
类提供,DataImporter
需要消耗不少时间完成初始化:因为它的实例在初始化时可能要打开文件,还要读取文件内容到内存。
DataManager
也可能不从文件中导入数据。所以当DataManager
的实例被创建时,没必要创建一个DataImporter
的实例,更明智的是当用到DataImporter
的时候才去创建它。
由于使用了@lazy
,importer
属性只有在第一次被访问的时候才被创建。比如访问它的属性fileName
时:
println(manager.importer.fileName)
// DataImporter 实例的 importer 属性现在被创建了
// 输出 "data.txt”