Swift协议,用于与String相互转换的事物

时间:2019-11-07 15:01:18

标签: swift swift-protocols rawrepresentable

我想拥有一个GenericThing,其模板参数可以是可以明智地在字符串之间进行转换的任何类型。

// ConvertsToAndFromString is a made up protocol here – what should I use instead?
struct GenericThing<Id: ConvertsToAndFromString> {
}

然后,我应该能够将GenericThing与任何具有合理编码的类型一起使用为字符串。例如,它应该适用于IntString(嗯,嗯),理想情况下,RawRepresentable本身RawValue本身将在字符串之间进行转换的任何enum Tubbies: String { case dipsy case laalaa case po } // I'd like to be able to do this. let genericThing = GenericThing<Tubbies> 。 / p>

示例:

LosslessStringConvertible

我看不出如何轻松地做到这一点。

我希望我可以使用ConvertsToAndFromString来代替Int

我尝试了此方法,它适用于Tubbies等。但这不适用于RawRepresentable。我看不到一种使所有RawValue: LosslessStringConvertible也符合LosslessStringConvertible的{​​{1}}的方法。

2 个答案:

答案 0 :(得分:1)

这是您根据其RawRespresentableLosslessStringConvertible扩展为有条件RawValue的方式:

extension RawRepresentable where RawValue: LosslessStringConvertible {
    init?(_ rv: RawValue) {
        self.init(rawValue: rv)
    }

    var description: String { return self.rawValue.description }
}

这里正在起作用:

struct GenericThing<Id: LosslessStringConvertible> {

}

enum Tubbies: String, LosslessStringConvertible {
    case dipsy
    case laalaa
    case po
}

let genericThing = GenericThing<Tubbies>()
print(Tubbies.po is LosslessStringConvertible) // => true

答案 1 :(得分:0)

至少在 Swift 5.2 中存在一个问题,即扩展 RawRepresentable 导致 CodingKeys 编译失败。

public extension RawRepresentable where RawValue: LosslessStringConvertible {
    init?(_ rv: RawValue) { self.init(rawValue: rv) }
    var description: String { rawValue.description }
}

struct Test: Codable {
    public var test: String
    enum CodingKeys: String, CodingKey { // Error: Type 'Test.CodingKeys' does not conform to protocol 'CustomStringConvertible'
        case test = "foo"
    } 
}

我的解决方法是使用相同的策略显式添加一致性,它需要能够更改枚举但允许 CodingKeys 进行编译。

public protocol LosslessStringConvertibleEnum: LosslessStringConvertible, 
    RawRepresentable where RawValue: LosslessStringConvertible {}

public extension LosslessStringConvertibleEnum {
    init?(_ rawValue: RawValue) { self.init(rawValue: rawValue) }
    var description: String { rawValue.description }
}

enum Tubbies: String, LosslessStringConvertibleEnum {
    case dipsy
    case laalaa
    case po
}