Как инициализировать литералами для обобщенного типа c? - PullRequest
1 голос
/ 28 апреля 2020

Есть протоколы для достижения инициализации с литералами.

Примеры: Используя ExpressibleByStringLiteral, мы можем сделать следующее:

struct MyString: ExpressibleByStringLiteral {
    let value: String

    init(stringLiteral value: String) {
        self.value = value
    }
}

let str: MyString = "Hello World!" // It's the same as: `MyString(stringLiteral: "Hello World!")`
str.value // "Hello World!"

Также, с помощью используя ExpressibleByIntegerLiteral, мы можем сделать следующее:

struct MyInt: ExpressibleByIntegerLiteral {
    let value: Int

    init(integerLiteral value: Int) {
        self.value = value
    }
}

let int: MyInt = 101 // It's the same as: `MyInt(integerLiteral: 101)`
int.value // 101

Мой вопрос:

Как мы можем применить те же логики c для структуры с универсальный c тип? Представьте, что у меня есть следующая структура:

struct MyCustom<T> {
    let value: T
}

Что я хочу сделать, это:

let custom1: MyCustom = "Hello World!"
custom1.value // "Hello World!"
// OR (since its generic)
let custom2: MyCustom = 101
custom1.value // 101

Какому соответствующему протоколу соответствовать в этом случае?

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Нет 1 протокола, которому вы могли бы соответствовать, но вы можете создать условное соответствие всем ExpressibleByXLiteral протоколам на основе общего c типа T.

extension MyCustom: ExpressibleByUnicodeScalarLiteral, ExpressibleByExtendedGraphemeClusterLiteral, ExpressibleByStringLiteral where T == String {
    init(unicodeScalarLiteral value: T) {
        self.value = value
    }

    init(extendedGraphemeClusterLiteral value: T) {
        self.value = value
    }

    init(stringLiteral value: T) {
        self.value = value
    }
}

extension MyCustom: ExpressibleByIntegerLiteral where T == Int {
    init(integerLiteral value: T) {
        self.value = value
    }
}

let myString: MyCustom<String> = "String"
let myInt: MyCustom<Int> = 21
2 голосов
/ 28 апреля 2020

Это возможно с условными соответствиями:

extension MyCustom: ExpressibleByStringLiteral, ExpressibleByUnicodeScalarLiteral, ExpressibleByExtendedGraphemeClusterLiteral where T: ExpressibleByStringLiteral {
    init(stringLiteral value: T.StringLiteralType) {
        self.value = T(stringLiteral: value)
    }

    init(unicodeScalarLiteral value: T.UnicodeScalarLiteralType) {
        self.value = T(unicodeScalarLiteral: value)
    }

    init(extendedGraphemeClusterLiteral value: T.ExtendedGraphemeClusterLiteralType) {
        self.value = T(extendedGraphemeClusterLiteral: value)
    }
}

extension MyCustom: ExpressibleByIntegerLiteral where T: ExpressibleByIntegerLiteral {
    init(integerLiteral value: T.IntegerLiteralType) {
        self.value = T(integerLiteral: value)
    }
}

С этим вы можете сделать:

let custom1: MyCustom<String> = "Hello World!"
custom1.value // "Hello World!"
// OR (since its generic)
let custom2: MyCustom<Int> = 101
custom2.value // 101

Для ExpressibleByStringLiteral вам нужно явно указать и реализовать унаследованные соответствия, хотя.

Кроме того, вам необходимо указать Swift, какой тип обобщенного типа c вы хотите (MyCustom<Int> и MyCustom<String>), поскольку могут существовать другие типы, например ExpressibleByIntegerLiteral. Например, сам тип MyCustom:

let custom3: MyCustom<MyCustom<Int>> = 101
custom3.value // MyCustom<Int>(value: 101)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...