问题描述
所以我在玩协议扩展时遇到了一个有趣"的问题.
So I was playing around with protocol extensions and i ran into an "interesting" problem.
我想写一个 Meters
和 Kilometers
单位类型来测试一些东西.作为一个有基类并且两个子类都覆盖基类的类很容易做到这一点,而只是覆盖一个简单的值
I wanted to write a Meters
and Kilometers
units type for testing some things out. Its VERY easy to do this as a class where there is a base class and both sub classes override the base, while just overriding a simple value
//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
}
}
如你所见,我有很多重复的代码(特别是初始化程序)
So as you can see i have lots of duplicate code (specifically the initializers)
我试图做一个协议扩展来设置默认初始化器
I tried to make a protocol extension to set the default initializer
extension DistanceUnit {
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
但我收到一个错误,变量'self'在初始化之前通过引用传递
有什么办法可以让它工作,还是我只需要输入大量重复的代码?也许使用 unsafe
之类的?
Is there any way to get this to work or do i just have to type lots of duplicate code? Maybe using unsafe
or something?
推荐答案
我认为 fqdn
是正确的,我们将无法像我们希望的那样在协议扩展中使用自定义初始化,但只有时间会证明一切.
I assume that fqdn
is right and we won't be able to use custom inits inside protocols extension as we would like to, but only time will tell.
但仍有一些解决方法:
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))
}
}
希望能帮到你.几天前,我在构建带有协议扩展的自定义通用单例生成器时学到了这个技巧(参见此处).
Hope that will help you. I learned this trick a few days ago when i was building a custom generic singleton generator with protocol extensions (see here).
这篇关于swift2 中协议扩展和默认值的限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!