Swift中的计算属性和存储值属性有什么区别?

时间:2018-08-29 13:54:45

标签: swift xcode properties

问题:

Row.swift 中的两行有什么区别?

上下文:

Row.swift

open class Row {

  // Existing code (Good):
  public var cellIdentifier: String { return String(describing self) }

  // The change (Bad):
  public var cellIdentifier: String = String(describing: self)

DifferentRow.swift

public class DifferentRow: Row {

  public override var cellIdentifier: String { return "\(super.cellIdentifier)" }
  // returns the error below

错误:

不能用只读属性'cellIdentifier'覆盖可变属性

3 个答案:

答案 0 :(得分:2)

此:

public var cellIdentifier: String { return String(describing self) }

定义了计算属性。没有值被存储。每次您访问cellIdentifier时,闭包都会运行并返回String。它是只读的,因为仅提供了getter。

此:

public var cellIdentifier: String = String(describing: self)

存储值属性,它是可读写的。

该错误告诉您不能将具有读/写功能的属性替换为仅具有读功能的属性。

注意:如果您要使用值初始化属性,则无法访问self,因为self直到对象都代表了类/结构实例已完全初始化。如果将属性设置为lazy var,则可以在初始化中使用self,因为该属性将在首次访问时被初始化。

您可以了解有关Swift属性here in the Swift Language Guide

的更多信息

答案 1 :(得分:1)

您不能使用只能读取的属性来覆盖“读取和写入”属性。

您可以分配其他值:

public override var cellIdentifier: String = “newValue”

或创建一个set和一个get实现:

public override var cellIdentifier: String {
    get { return “\(super.cellIdentifier)” }
    set { super.cellIdentifier = newValue }
}

Computed Properties下,详细了解此syntax

答案 2 :(得分:0)

我认为错误消息令人困惑。

问题

public var cellIdentifier: String = String(describing: self)

是对self的引用:

  • 在定义过程中分配cellIdentifier时,self不能保证完全初始化。
  • 因此,禁止调用函数(如String(describing:))并上交半初始化的self

一种解决方案可能是使cellIdentifier成为惰性属性:

public lazy var cellIdentifier: String = String(describing: self)

这将自动将函数调用延迟到初始化完成之后的时间。