代码截图
代码出处: Swift Tips 029 by John Sundell[1]
小笔记
这段代码在说什么
今天的这段代码为 Node 类设置了两个 readonly 的属性:parent 和 children,与其他 read only 属性不太一样的地方是:它们并没有显式的声明 getter 方法,而且看起来也不怎么像一个计算属性(因为只有计算属性才能 read only)。
通过为计算属性设置 get 和 set 方法,就可以实现计算属性的只读(只实现 get),可读可写(get 和 set),如果你想了解更多,可以阅读官方手册的属性章节[2]。需要注意的是,这里要区分存储属性和计算属性!
简洁优雅的 private(set)
如果你问一个 Swift 开发者:如果想声明一个公开 getter,隐藏 setter 的属性,最简洁最优雅的方式是什么。
我想九成的开发者会说 ---- private(set)
但是你有没有好奇过这个“简洁优雅”的由来,如果不用 private(set)
的话怎么做呢?
实现一个相同的功能吧
怎么看 parent
和 children
都像个存储属性,但它又做到了 read only,那么它到底是怎么实现只读的呢?
如果你没想到怎么做,来看看下面的代码吧,当然可行的解决方案有很多,下面只是其中一个而已!
class Node {
private weak var _parent: Node?
var parent: Node? {
return _parent
}
private lazy var _children = [Node]( "Node")
var children: [Node] {
return _children
}
func add(child: Node) {
_children.append(child)
child._parent = self
}
}
现在你能理解了么?
我们通过内置一个 private 访问级别的属性(_parent
,_children
)来持有真正的值,但向外只暴露一个与此关联的计算属性(parent
, children
),通过这种方式我们实现了与 private(set)
相同的效果。
再多说一点
很显然,private(set)
让代码变得更加简洁和优雅了!但是如果我想改变 getter 方法的访问等级,又该怎么办呢?
如果你不理解访问等级,建议阅读官方手册里关于访问控制一节的内容[3]
很简单,你只需要在 private(set)
前面加上对应的访问等级修饰符即可改变 getter 方法的访问等级了,例如下面的代码就将 parent
属性的 getter 方法变为了 public 级别。
public private(set) weak var parent: Node?
说了这么多,今天的这个 tip 你喜欢么?