Как разрешить перекрывающиеся соответствия CustomStringConvertible - PullRequest
0 голосов
/ 09 января 2020

Основываясь на этой статье Джона Санделла, у меня есть следующая структура:

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, а другое один игнорируется. И я не могу добавить соответствие другому расширению, так как они будут перекрываться.

print(Identifier<A>(stringLiteral: "string")) // prints "string"
print(Identifier<B>(integerLiteral: 5)) // prints "Identifier<B>(rawValue: 5)"

1 Ответ

1 голос
/ 09 января 2020

Вы можете использовать одно расширение CustomStringConvertible вместо двух, которые у вас есть на данный момент, независимо от типа:

extension Identifier: CustomStringConvertible {
    var description: String {
        "\(rawValue)"
    }
}

Для меня это правильно печатает «string», а затем «5» в соответствии с вашим последний пример кода.

По совпадению, это то, что делает Sundell в своей реализации Идентификации с открытым исходным кодом Идентифицируемый / Идентификатор - 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

...