有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
在这种情况下符合什么合适的协议?
这可以通过条件符合:
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)
没有可以遵循的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