我想要一个带有模板参数的GenericThing
,它是可以合理地转换为字符串和从字符串转换为字符串的任何类型。
// ConvertsToAndFromString is a made up protocol here – what should I use instead?
struct GenericThing<Id: ConvertsToAndFromString> {
}
然后,我应该能够将GenericThing
与任何具有合理编码的类型一起用作字符串。例如,它应该适用于Int
、String
(好吧,dah(,理想情况下,适用于任何RawRepresentable
,其中RawValue
本身将转换为字符串或从字符串转换而来。
示例:
enum Tubbies: String {
case dipsy
case laalaa
case po
}
// I'd like to be able to do this.
let genericThing = GenericThing<Tubbies>
我看不出如何轻易做到这一点。
我希望我能用LosslessStringConvertible
而不是我编的ConvertsToAndFromString
。
我试过这个,它适用于Int
等。但它不适用于Tubbies
。我看不出一种方法可以使所有的RawRepresentable
,其中RawValue: LosslessStringConvertible
也符合LosslessStringConvertible
。
这就是如何根据RawValue
:将RawRespresentable
扩展为有条件的LosslessStringConvertible
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
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
}