如何解决 CustomStringConvertible 的重叠一致性问题
How to resolve overlapping conformances of CustomStringConvertible
基于 John Sundell 的article,我有以下结构:
protocol Identifiable {
associatedtype RawIdentifier: Codable, Hashable = String
var id: Identifier<Self> { get }
}
struct Identifier<Value: Identifiable>: Hashable {
let rawValue: Value.RawIdentifier
init(stringLiteral value: Value.RawIdentifier) {
rawValue = value
}
}
extension Identifier: ExpressibleByIntegerLiteral
where Value.RawIdentifier == Int {
typealias IntegerLiteralType = Int
init(integerLiteral value: IntegerLiteralType) {
rawValue = value
}
}
它可以是 String 或 Int。为了能够简单地打印它(无需使用 .rawValue
),我添加了以下扩展:
extension Identifier: CustomStringConvertible where Value.RawIdentifier == String {
var description: String {
return rawValue
}
}
extension Identifier where Value.RawIdentifier == Int {
var description: String {
return "\(rawValue)"
}
}
问题是,它只对符合CustomStringConvertible 的extension 起作用,而另一个被忽略。而且我无法将一致性添加到其他扩展,因为它们会重叠。
print(Identifier<A>(stringLiteral: "string")) // prints "string"
print(Identifier<B>(integerLiteral: 5)) // prints "Identifier<B>(rawValue: 5)"
您可以使用单个 CustomStringConvertible
扩展名而不是目前的两个扩展名,无论类型如何:
extension Identifier: CustomStringConvertible {
var description: String {
"\(rawValue)"
}
}
对我来说,这正确地打印了 "string",然后是你上一个代码示例中的“5”。
这恰好是 Sundell 在其 Identifiable/Identifier 的开源身份实现中所做的 – https://github.com/JohnSundell/Identity/blob/master/Sources/Identity/Identity.swift#L72-L78
Point-Free 的 'Tagged' 实现也值得参考:https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift
基于 John Sundell 的article,我有以下结构:
protocol Identifiable {
associatedtype RawIdentifier: Codable, Hashable = String
var id: Identifier<Self> { get }
}
struct Identifier<Value: Identifiable>: Hashable {
let rawValue: Value.RawIdentifier
init(stringLiteral value: Value.RawIdentifier) {
rawValue = value
}
}
extension Identifier: ExpressibleByIntegerLiteral
where Value.RawIdentifier == Int {
typealias IntegerLiteralType = Int
init(integerLiteral value: IntegerLiteralType) {
rawValue = value
}
}
它可以是 String 或 Int。为了能够简单地打印它(无需使用 .rawValue
),我添加了以下扩展:
extension Identifier: CustomStringConvertible where Value.RawIdentifier == String {
var description: String {
return rawValue
}
}
extension Identifier where Value.RawIdentifier == Int {
var description: String {
return "\(rawValue)"
}
}
问题是,它只对符合CustomStringConvertible 的extension 起作用,而另一个被忽略。而且我无法将一致性添加到其他扩展,因为它们会重叠。
print(Identifier<A>(stringLiteral: "string")) // prints "string"
print(Identifier<B>(integerLiteral: 5)) // prints "Identifier<B>(rawValue: 5)"
您可以使用单个 CustomStringConvertible
扩展名而不是目前的两个扩展名,无论类型如何:
extension Identifier: CustomStringConvertible {
var description: String {
"\(rawValue)"
}
}
对我来说,这正确地打印了 "string",然后是你上一个代码示例中的“5”。
这恰好是 Sundell 在其 Identifiable/Identifier 的开源身份实现中所做的 – https://github.com/JohnSundell/Identity/blob/master/Sources/Identity/Identity.swift#L72-L78
Point-Free 的 'Tagged' 实现也值得参考:https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift