Swift 4.1中正确重写lazy var的方法是什么?
正确重写Swift中lazy属性的方法
嘿,这个坑我踩过!Swift 4.0里那种直接子类重写父类lazy存储属性的写法其实是编译器的“漏网之鱼”,从4.1开始官方明确把它标记为不符合规范的写法,弹出「Cannot override with a stored property myVar」的警告,而且后续版本(比如Swift 5+)确实有完全禁用的风险,所以得换成标准的写法才行。
为什么之前能行现在不行?
本质上Swift的语法规则里,子类是不允许直接重写父类的存储属性的——不管这个属性是不是lazy的。4.0版本的编译器没做严格检查,所以侥幸通过了,但后续版本收紧了规则,这也是为了保证代码的一致性和避免潜在的内存/初始化问题。
几种优雅的解决方案
方案1:子类维护私有lazy存储 + 重写计算属性
如果父类是你无法修改的(比如第三方库),这是最稳妥的方式:
class A { lazy var myVar: String = { return "A" }() } class B: A { // 子类自己维护私有lazy变量 private lazy var _myVar: String = { return "B" }() // 重写父类属性为计算属性,指向自己的私有存储 override var myVar: String { get { _myVar } set { _myVar = newValue } } }
这种写法既保留了lazy延迟初始化的特性,又完全符合Swift的属性重写规则,不会触发任何警告。
方案2:把父类属性改为计算属性(若可修改父类)
如果你能修改父类的代码,把父类的lazy存储属性改成返回lazy值的计算属性,子类直接重写这个计算属性会更简洁:
class A { var myVar: String { lazy var innerValue = "A" return innerValue } } class B: A { override var myVar: String { lazy var innerValue = "B" return innerValue } }
这种方式更符合Swift的设计理念,每个子类都可以独立实现自己的lazy初始化逻辑,代码也更清爽。
方案3:使用方法替代属性(可选)
如果你的lazy属性逻辑比较复杂,也可以把它包装成方法,子类重写方法:
class A { private lazy var _myVar: String? = nil func getMyVar() -> String { if _myVar == nil { _myVar = "A" } return _myVar! } } class B: A { private lazy var _mySubVar: String? = nil override func getMyVar() -> String { if _mySubVar == nil { _mySubVar = "B" } return _mySubVar! } }
不过这种方式需要调用方法而不是访问属性,适合对属性访问形式要求不高的场景。
内容的提问来源于stack exchange,提问作者Arnaud Dorgans
相关产品推荐
相关产品推荐

