Limits of Protocol Extensions and defaults in swift2

隐身守侯 提交于 2019-12-10 09:56:31

问题


So I was playing around with protocol extensions and i ran into an "interesting" problem.

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
    }
}

but I get an error of variable 'self' passed by reference before being initalized

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?


回答1:


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.

But there is still some workaround:

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).



来源:https://stackoverflow.com/questions/31207908/limits-of-protocol-extensions-and-defaults-in-swift2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!