Mock CMMotionManager遇属性重写错误:无法用只读属性覆盖可变属性
问题:Mock CMMotionManager时deviceMotionUpdateInterval重写编译错误
我正在为单元测试Mock CMMotionManager,简化后的代码如下:
protocol XMotionManager { var isDeviceMotionAvailable: Bool { get } var deviceMotionUpdateInterval: TimeInterval { get set } } extension CMMotionManager: XMotionManager {} final class MockCMMotionManager: CMMotionManager { private (set) var mockedIsDeviceMotionAvailable = true override var isDeviceMotionAvailable: Bool { mockedIsDeviceMotionAvailable } private var mockedDeviceMotionUpdateInterval: TimeInterval = 1.0 override var deviceMotionUpdateInterval: TimeInterval { mockedDeviceMotionUpdateInterval } }
协议内容来自API,MockCMMotionManager本应重写这两个属性以便按需设置。其中isDeviceMotionAvailable重写正常,但deviceMotionUpdateInterval出现编译错误:
Cannot override mutable property with read-only property 'deviceMotionUpdateInterval'
我不理解该错误,因为deviceMotionUpdateInterval是var声明的可变属性,并非只读。请问我的代码存在什么问题?
问题原因
你重写的deviceMotionUpdateInterval只实现了getter(只读),但父类CMMotionManager中的这个属性是读写属性(同时支持get和set操作)。Swift的重写规则要求:子类重写父类的属性时,不能缩小其访问权限——不能把读写属性改成只读属性。
看你的代码实现:
private var mockedDeviceMotionUpdateInterval: TimeInterval = 1.0 override var deviceMotionUpdateInterval: TimeInterval { mockedDeviceMotionUpdateInterval }
这段代码本质上只提供了getter的逻辑,没有实现setter,所以编译器判定你把原本的可变属性改成了只读,因此抛出错误。
解决方法
给重写的属性补充setter实现,保持其读写权限即可:
private var mockedDeviceMotionUpdateInterval: TimeInterval = 1.0 override var deviceMotionUpdateInterval: TimeInterval { get { mockedDeviceMotionUpdateInterval } set { mockedDeviceMotionUpdateInterval = newValue } }
这样既遵循了父类属性的读写特性,又能通过mockedDeviceMotionUpdateInterval来灵活控制属性值,满足单元测试的Mock需求。
如果希望外部只能通过Mock的方式修改这个值,可以给mockedDeviceMotionUpdateInterval加上private(set)限制,但重写的属性本身必须保留setter:
private(set) var mockedDeviceMotionUpdateInterval: TimeInterval = 1.0 override var deviceMotionUpdateInterval: TimeInterval { get { mockedDeviceMotionUpdateInterval } set { mockedDeviceMotionUpdateInterval = newValue } }
内容的提问来源于stack exchange,提问作者Reinhard Männer
相关产品推荐
相关产品推荐

