我有这堂课:
class ListView: UIView {
var labels: [UnderlineLabel]
var listItems: [String] { return [] }
var areUnselectable: Bool { return false }
...
}
到目前为止,我一直在使用这个类,通过继承它并覆盖它的计算属性。但现在我处于需要使用此类的情况,但我需要做的唯一更改是listItems
属性(提供字符串列表,转换为UnderlineLabels
,可以选择(加下划线))。因此,我正在考虑而不是将ListView
子类化为这样一个微不足道的变化,对于单个用例,重构该类以使其能够通过组合使用会更好。
我只能提出一个允许我保留计算属性语义(listItems
而不是getListItems()
)的解决方案,并通过覆盖提供子类的可定制性,并通过初始化提供实例化器:
创建一个额外的存储属性,可能是private let getListItems: (() -> [String])?
返回结果,或默认情况下[]
nil
listItems
通过在getListItems
init
醇>
这是获得我想要的能力的唯一途径吗?如果没有,是否有更明确的方法来做到这一点?
请记住,listItems
是计算属性的原因是为列表提供在执行期间更改的能力。
答案 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,即使它什么都不做。
对于它的价值,我不认为这是好的代码。