所以我在研究协议扩展时遇到了一个“有趣”的问题。
我想写一个Meters
and Kilometers
用于测试某些东西的单元类型。作为一个类,它非常容易做到这一点,其中有一个基类,并且两个子类都覆盖基类,而只是覆盖一个简单的值
//Conversion factor between types
enum DISTANCE_UNIT_TYPE : Double {
case METER = 1.0;
case KILOMETER = 0.001;
}
protocol DistanceUnit {
var unitType : DISTANCE_UNIT_TYPE {get}
var value : Double { get set }
var baseValue : Double { get set }
}
struct Kilometers : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.KILOMETER
var value : Double
var baseValue : Double
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
struct Meters : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.METER
var value : Double
var baseValue : Double
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
正如你所看到的,我有很多重复的代码(特别是初始化程序)
我尝试制作协议扩展来设置默认初始化程序
extension DistanceUnit {
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
但我得到一个错误变量“self”在初始化之前通过引用传递
有什么方法可以让它工作,还是我只需要输入大量重复的代码?也许使用unsafe
或者其他的东西?
我假设fqdn
是对的,我们将无法像我们希望的那样在协议扩展中使用自定义 inits,但只有时间才能证明一切。
但仍有一些解决方法:
struct Meters : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.METER
var value : Double
var baseValue : Double
init() { // this one is needed as designated initializer for your protocol extension
value = 0
baseValue = 0
}
}
protocol DistanceUnit {
var unitType : DISTANCE_UNIT_TYPE {get}
var value : Double { get set }
var baseValue : Double { get set }
init() // this is new and you will NEED to implement this in your structure or class
}
extension DistanceUnit {
init(_ v : Double) {
self.init()
value = v
baseValue = v * unitType.rawValue
}
// you can now implement a lot more different default inits and they should work fine here :)
// here is a quick example
init(_ s : String) {
self.init(Double(s.characters.count))
}
}
希望这会对您有所帮助。几天前,当我构建带有协议扩展的自定义通用单例生成器时,我学到了这个技巧(see here https://stackoverflow.com/a/31270708/4572536).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)