# 延迟计算属性
####有关延迟计算属性的问题
首先,延迟计算属性本质上就是一个闭包,如果调用的时候这个属性有值则直接使用,如果没有值则触发闭包的调用
我们举个例子,创建一个简单的闭包
let myClosure = {()->String in
return "testString"
}
######注意:闭包的灵活之处在于可以根据上下文推断出自身的类型,大家不妨把()->String in 这段代码删掉,其实效果是一样的。这很重要,官方有句话大致这个意思“事实上你可能不必写出任何一个完整格式的闭包表达式”,说的就是闭包的灵活性问题
我们再声明一个类,这个类里有一条属性是一个闭包类型,当然我一定会设计成()->String类型的,不然上面的闭包就没有用处了
class Student {
var words:()->String
init(words:()->String) {
self.words = words
}
func say() {
// 这里如果我希望把学生的words打印出来,就需要调用闭包,调用闭包一定要使用括号,因为别忘了,闭包本质就是匿名函数。
print("学生的话:\(self.words())")
}
}
现在创建一个Student实例,把myClosure作为参数,再调用他的say函数
let xiaoMing = Student(words: myClosure)
xiaoMing.say()
打印结果如下
学生的话:testString
现在我把上面的例子稍作修改,我们使用一个字符串类型的属性去记录学生要说的话,而学生的话仍然有这个闭包获取,那么上面的程序变成下面的样子
class Student {
var words:()->String
init(words:()->String) {
self.words = words
}
// 因为闭包获取的值编译器无法确定获取时间,所以不能再实例初始化一开始就赋值,所以这个message属性必须使用lazy来声明,并且它必须是var类型,因为它必须是可写入的
// lazy var message:String = self.words()
// 如果上面这行代码可以如上那样写,那么一定也可以如下这样写
lazy var message:String = {()->String in
return "closureString"
}()
func say() {
// 这里我们就可以把之前的闭包调用,改成属性的调用了
print("学生的话:\(self.message)")
}
}
我们在实例化学生对象来观察结果
let xiaoHong = Student(words: myClosure)
xiaoHong.say()
打印结果如下
学生的话:closureString
所以这个时候,我们想实现最开始的功能,可以把程序修改成如下的样子
class Student {
func say() {
print("学生的话:\(self.message)")
}
// lazy var message:String = {()->String in
// return "closureString"
// }()
// 由于闭包可以自动推断自身的类型,所以可以省略成这个样子
lazy var message:String = {
return "closureString"
}()
}
最终我们的程序变成下面的样子了
class Student {
func say() {
print("学生的话:\(self.message)")
}
lazy var message:String = {
return "closureString"
}()
}
是不是很简洁?所以在使用延迟计算属性的时候,不要忘记后面的小括号
网友评论