编程Swift开发者

解释Swift中computed property的工作机制。computed属性和stored属性之间的主要区别是什么,computed属性的用途是什么?

用 Hintsage AI 助手通过面试

答案。

历史上,Objective-C中的属性通过访问方法(getter和setter)实现。在Swift中,引入了一种特殊的语法结构用于computed properties,使得创建“动态”计算其值的属性变得简单。这扩展了类型封装和代码表达能力。

问题: 并不总是方便将结果作为stored property存储,尤其是当值依赖于其他属性或不断变化时。使用计算方法会构建一个可读性较差的类型接口,隐藏了其本质。

解决方案: Computed property通过get和(如有必要)set进行定义。每当访问此类属性时,都会执行计算,而不是从内存中读取。这允许创建与对象其余状态自动同步的derived properties。

代码示例:

struct Rectangle { var width: Double var height: Double var area: Double { get { return width * height } set { // 自动更新width以适应新的area值(示例) width = sqrt(newValue / height) } } } var rect = Rectangle(width: 5, height: 2) print(rect.area) // 10 rect.area = 36 print(rect.width) // 3.0

关键特性:

  • Computed property不占用额外的内存,其结果不会自动存储。
  • 可以只有get或同时有get和set。
  • 创建derived或同步属性的便利方式。

令人困惑的问题。

可以在computed property中使用willSet/didSet吗?

不可以,willSet和didSet仅适用于stored property。对于computed property,这些观察者不工作,因为没有自动存储值。

computed property可以具有弱引用或隐式展开类型吗?

可以,computed property可以是可选的或隐式展开的。但是,做这样的属性为weak是没有意义的,因为它们不包含引用——只有计算。

在什么情况下更适合在computed property中使用private set?

访问修饰符private(set)不能应用于具有get和set的computed property,只能用于stored property。对于computed property,set可以通过private set完全私有,但这是通过set块的可用性隐式实现的。

public var area: Double { private set { ... } get { ... } }

常见错误和反模式

  • 在get块中执行繁重、耗时的计算,导致性能下降。
  • 在getter内部修改状态,这违反了无副作用访问器的概念。
  • 错误地使用set,当改变一个属性时应影响多个其他属性。

生活中的例子

负面案例

getter的computed property每次访问时从网络加载大量数据,导致卡顿和网络过载。

优点:

  • 对于小数据来说易于使用。

缺点:

  • 脆弱性和在真实数据上的不可预测行为。
  • 对性能和能耗造成显著负面影响。

正面案例

computed property基于其他stored property以最低的开销计算最终值,耗时的逻辑缓存放在单独的机制中。

优点:

  • 高性能。
  • 状态同步和可预测的工作契约。

缺点:

  • 如果计算复杂,可能需要额外的代码用于缓存。