通过初始化使计算属性可自定义

时间:2017-12-26 23:41:20

标签: swift

我有这堂课:

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. 通过在getListItems

  4. 中传递自定义值来初始化init

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

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

2 个答案:

答案 0 :(得分:0)

我可能最终会这样做

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

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

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

答案 1 :(得分:0)

使用计算属性覆盖存储的属性是合法的。所以这有效:

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

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

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

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