iOS中Swift从开始入门到最后的放弃(十3,

# 延迟计算属性

####有关延迟计算属性的问题

首先,延迟计算属性本质上就是一个闭包,如果调用的时候这个属性有值则直接使用,如果没有值则触发闭包的调用

我们举个例子,创建一个简单的闭包

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"

}()

}

是不是很简洁?所以在使用延迟计算属性的时候,不要忘记后面的小括号

你可能感兴趣的:(iOS中Swift从开始入门到最后的放弃(十3,)