每次访问计算属性时都会对其进行评估吗?
Posted
技术标签:
【中文标题】每次访问计算属性时都会对其进行评估吗?【英文标题】:Are computed properties evaluated every time they are accessed? 【发布时间】:2016-05-06 01:46:58 【问题描述】:我有两个关于 Swift 计算属性的问题。
或者它们存储在某个地方以备将来访问?
这是什么属性,我google也搜不出来:
let navigationController: UINavigationController =
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
()
每次访问时也会评估它吗?
【问题讨论】:
【参考方案1】:这不是计算属性。
let navigationController: UINavigationController =
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
()
它只是一个存储属性,填充了这段代码返回的值的结果。
var navigator = UINavigationController()
navigator.navigationBar.translucent = false
return navigator
当类的实例被实例化时,块被执行。只有一次。
所以写这个
struct Person
let name: String =
let name = "Bob"
return name
() // <- look at these
与此等价
struct Person
let name: String
init()
self.name = "Bob"
恕我直言,第一种方法更好,因为:
它确实允许您在相同的“空间”中声明和填充属性 更清晰 如果您有多个初始化程序,确实可以防止重复代码注意 #1:在属性中存储闭包
正如 dfri 在下面的评论中指出的那样,代码块确实以 ()
结尾。这意味着代码已求值并将结果分配给属性。
另一方面,如果我们删除块末尾的()
,我们会得到不同的结果,实际上该块是未评估的。
在这种情况下,Swift 尝试将 stored closure
分配给该属性。这将产生编译错误,因为该属性的类型为 UINavigationController
。
使用正确的语法,我们可以在属性中放置一个闭包。
struct Person
let sayHello: ()->() = print("Hello")
现在我们有了一个包含闭包的sayHello
属性。闭包接收 0 个参数并返回 Void
。
let bob = Person()
bob.sayHello // this does NOT execute the code inside closure
bob.sayHello() // this does execute the code in the closure and does print the message
注意 #2:让我们谈谈计算属性
所以我们明确指出,这个问题中的代码不是Computed Property
。
但是,正如 EmilioPelaez 在下面的另一条评论中指出的那样,我们还应该声明Computed Property
每次被访问时都会被评估。
在下面的示例中,我创建了一个计算属性age
。正如你所看到的,每次我调用它时,块中的代码也会被执行。
计算属性示例 (age
)
【讨论】:
是的,代码只执行一次。您可以在该代码块中添加print("Test")
并验证它。
可能值得一提的是,最后大括号后的()
是这里的关键(通过运行匿名闭包块来初始化navigationController
属性)。例如。删除最后的()
并“稍微” 将顶行修改为let navigationController: () -> (UINavigationController) = ...
将产生一个存储的闭包,该闭包返回UINavigationController
实例和.translucent = false
。这个闭包又可以用来代替上面的匿名块,即用闭包名称代替 ...
块:let myNavigationController = navigationController()
。
@dfri:我完全同意。我会在我的回答中加入这个考虑。谢谢。
第一个问题的答案也应该加上,计算机属性每次访问都是计算机。
@appzYourLife 最后一点:我删除了()
,但还必须将UINavigationController
类型替换为闭包类型... : () -> (UINavigationController) = ...
,而不是之前的... : UINavigationController = ...
。如果我们在这里只删除()
,我们会得到一个编译时错误。但是,我们可以将显式类型排除在外,让 Swift 来推断这些类型,例如对于let foo = () -> Int in 1 ()
,最终的()
是将1
分配给foo
(包括最终的()
,=> foo
是Int
)或将() -> Int
闭包分配给foo
之间的唯一区别(省略()
)。以上是关于每次访问计算属性时都会对其进行评估吗?的主要内容,如果未能解决你的问题,请参考以下文章
Python类设置器 - 每次创建新实例时都会重新分配类属性吗?