ExpressibleByStringLiteral с опциями в параметрах функции - PullRequest
4 голосов
/ 05 августа 2020

Рассмотрим следующее перечисление

enum Text: Equatable {
    case plain(String)
    case attributed(NSAttributedString)
}

Я сделал его совместимым с ExpressibleByStringLiteral

extension Text: ExpressibleByStringLiteral {
    public typealias StringLiteralType = String
    
    public init(stringLiteral value: StringLiteralType) {
        self = .plain(value)
    }
}

Со всем этим я могу сделать следующее, как и ожидал :

let text: Text = "Hello" // .plain("Hello")
let text2: Text? = "Hello" // .plain("Hello")

Но я получаю следующие ошибки компилятора:

let nilString: String? = nil
let text3: Text? = nilString // Cannot convert value of type 'String?' to expected argument type 'Text?'

func foo(text: Text?) { /** foo **/ }
let text = "Hello"
foo(text: text) // Cannot convert value of type 'String' to expected argument type 'Text?'

func bar(text: Text?) { /** bar **/ }
bar(text: nilString) // Cannot convert value of type 'String?' to expected argument type 'Text?'

Как мне заставить их работать?

Я также пытался расширить Optional: ExpressibleByStringLiteral where Wrapped: ExpressibleByStringLiteral, но это не помогло.

1 Ответ

4 голосов
/ 05 августа 2020

ExpressibleByStringLiteral - это не автоматическое c приведение (String, Int) к вашему пользовательскому типу. Литерал - это точно "word" ( строковый литерал ) или 12.63 ( Двойной литерал ). Но в вашем примере let text = "Hello" постоянный текст имеет тип String . Но метод foo ожидает тип Text? для аргумента.

Но вы можете использовать его как

foo(text: "Some text")

Теперь компилятор знает, что он может преобразовать ваш строковый литерал в текст. А затем оберните его в Optional<Text>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...