【问题标题】:Making a computed property customizable through initialization通过初始化使计算属性可定制
【发布时间】:2017-12-26 23:41:19
【问题描述】:

我有这门课:

class ListView: UIView {

    var labels: [UnderlineLabel]

    var listItems: [String] {   return []   }
    var areUnselectable: Bool {   return false   }

...
}

到目前为止,我一直在使用这个类,方法是对它进行子类化并覆盖它的计算属性。但是现在我处于需要使用此类的情况,但我需要做的唯一更改是listItems 属性(它提供了字符串列表,转换为UnderlineLabels,并且可以选择(下划线))。因此,我认为与其子类 ListView 进行如此微不足道的更改以及单个用例,不如重构该类以支持组合使用。

我只能想出一种解决方案,它允许我保留计算属性语义(listItems 而不是 getListItems())并通过重写为子类提供可定制性,并通过初始化为实例化器提供可定制性:

  1. 创建一个额外的存储属性,可能是private let getListItems: (() -> [String])?

  2. 返回结果,如果nil,则返回[],默认为listItems

  3. 通过在init 中传递自定义值来初始化getListItems

这是获得我想要的功能的唯一方法吗?如果没有,是否有更明确的方法来做到这一点?

请记住,listItems 是计算属性的原因是为了让列表能够在执行期间更改。

【问题讨论】:

  • 您能否在引用字符串属性等时发布整个类,但定义中未显示它们。
  • @UpholderOfTruth 抱歉,为了清楚起见,为了这个问题,将名称改为listItems,并出于习惯使用strings 编写问题。编辑它

标签: swift


【解决方案1】:

我可能最终会这样做

class ListView: UIView {
    var labels: [UnderlineLabel]
    var listItems: [String]
    var areUnselectable: Bool {   return false   }

    init(strings: [String] = []) {
       listItems = strings
    }
...
}

您的解决方案也可以,但如果它只是一个不会修改的字符串数组,则不需要块。我希望我能正确理解你的问题。另外,我不确定你为什么需要计算它。

【讨论】:

  • 写错了问题,但需要计算它的原因是列表可以更改
  • 所以你不是返回一个空数组,而是另一个变量?因为返回一个空数组在任何时候都不会改变列表
【解决方案2】:

使用计算属性覆盖存储属性是合法的。所以这行得通:

class A {
    var listItems: [String] = []
}

class B: A {
    override var listItems: [String] {
        get { return [] }
        set { /* do nothing */ }
    }
}

注意子类中的空设置器。 listItems 属性是可变的,因此计算的覆盖需要一个 setter,即使它什么都不做。

对于它的价值,我认为这不是好的代码。

【讨论】:

  • 谢谢,但在我的情况下,listItems 可能与下一次调用不同,这就是它是计算属性的原因。如果您的A 的listItems 更改为() -> [String],则必须使用尾括号调用它,如果在B 中覆盖,则相同。这是我想将其保留为计算属性的主要原因 - 保留 listItems 语义与 getListItems()
猜你喜欢
  • 2019-01-25
  • 2014-10-15
  • 2019-11-07
  • 2019-06-21
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多