如何使用通用类型的文字进行初始化?

问题描述 投票:0回答:2

protocols用于实现文字的初始化。

示例:通过使用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

我的问题是:

我们如何为泛型类型的结构应用相同的逻辑?考虑我有以下结构:

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

在这种情况下符合什么合适的协议?

swift initialization swift-protocols
2个回答
0
投票

这可以通过条件符合:

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
custom1.value // 101

对于ExpressibleByStringLiteral,您需要显式声明和实现继承的一致性。

[此外,您可能需要告诉Swift您想要哪种泛型类型(MyCustom<Int>MyCustom<String>),因为可能还有其他类型符合例如ExpressibleByIntegerLiteral。例如MyCustom类型本身:

let custom3: MyCustom<MyCustom<Int>> = 101
custom3.value // MyCustom<Int>(value: 101)

0
投票

没有可以遵循的1种协议,但是您可以基于ExpressibleByXLiteral的通用类型为所有T协议创建条件一致性。

extension MyCustom: ExpressibleByUnicodeScalarLiteral where T == String {
    typealias UnicodeScalarLiteralType = T

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

extension MyCustom: ExpressibleByExtendedGraphemeClusterLiteral where T == String {
    typealias ExtendedGraphemeClusterLiteralType = T

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

extension MyCustom: ExpressibleByStringLiteral where T == String {
    typealias StringLiteralType = T

    init(stringLiteral value: Self.StringLiteralType) {
        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
© www.soinside.com 2019 - 2024. All rights reserved.