协议扩展的限制和swift2中的默认值

Jee*_*eef 3 protocols swift swift-protocols

所以我正在玩协议扩展,我遇到了一个"有趣"的问题.

我想写一个MetersKilometers单位类型测试一些东西出来.很容易做到这一点,因为有一个基类,两个子类都覆盖基类,而只是覆盖一个简单的值

//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
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以看到我有很多重复的代码(特别是初始化程序)

我尝试进行协议扩展以设置默认初始值设定项

extension DistanceUnit {

    init(_ v : Double) {
        value = v
        baseValue = v * unitType.rawValue
    }
}
Run Code Online (Sandbox Code Playgroud)

但是在被初始化之前我得到了一个由参考传递变量'self'的错误

有没有办法让这个工作或我只需要输入大量重复的代码?也许用unsafe或什么?

Dev*_*ist 5

我认为这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))
    }
}
Run Code Online (Sandbox Code Playgroud)

希望能帮到你.几天前,当我构建一个带有协议扩展的自定义通用单例生成器时,我学到了这个技巧(见这里).