简体   繁体   English

Swift 协议,用于与字符串相互转换的事物

[英]Swift protocol for things that convert to and from String

I'd like to have a GenericThing with a template parameter that is any type that can sensibly be converted to and from a string.我想要一个带有模板参数的GenericThing ,它是可以明智地转换为字符串和从字符串转换的任何类型。

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

I should then be able to use GenericThing with any type that has a reasonable encoding as a string.然后,我应该能够将GenericThing与具有合理编码为字符串的任何类型一起使用。 For example, it should work for Int , String (well, dah), and ideally, any RawRepresentable where the RawValue itself will convert to and from a string.例如,它应该适用于IntString (嗯,dah),理想情况下,适用于RawValue本身将转换为字符串和从字符串转换的任何RawRepresentable

Example:例子:

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

// I'd like to be able to do this.
let genericThing = GenericThing<Tubbies>

I can't see how to easily do this.我看不出如何轻松做到这一点。

I was hoping I could use LosslessStringConvertible instead of my made up ConvertsToAndFromString .我希望我可以使用LosslessStringConvertible而不是我编造的ConvertsToAndFromString

I tried this, and it works for Int and such.我试过这个,它适用于Int等。 But it doesn't work for Tubbies .但它不适用于Tubbies I couldn't see a way to make all RawRepresentable where RawValue: LosslessStringConvertible also conform to LosslessStringConvertible .我看不到让所有RawRepresentable的方法,其中RawValue: LosslessStringConvertible也符合LosslessStringConvertible

This is how you extend RawRespresentable to be conditionally LosslessStringConvertible depending on its RawValue :这就是您如何根据RawValueRawRespresentable扩展为有条件的LosslessStringConvertible

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

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

Here it is in action:这是在行动:

struct GenericThing<Id: LosslessStringConvertible> {

}

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

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

Had an issue in Swift 5.2 at least where extending RawRepresentable was causing CodingKeys to fail compiling.在 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"
    } 
}

My workaround was to instead explicitly add conformance using the same strategy, it requires being able to change the enum but allows CodingKeys to compile.我的解决方法是使用相同的策略显式添加一致性,它需要能够更改枚举但允许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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM