第七章——字符串(字符串字面量转换)

225 阅读2分钟

本文系阅读阅读原章节后总结概括得出。由于需要我进行一定的概括提炼,如有不当之处欢迎读者斧正。如果你对内容有任何疑问,欢迎共同交流讨论。

创建字符串变量有两种写法:String("something")"something",这两种写法效果一样但背后的原理不同。"something"是字符串字面量,在前面的章节我们已经介绍过数组字面量。

想通过字符串字面量创建字符串变量,比使用数组更复杂一些。我们看一下StringLiteralConvertible协议的定义:

public protocol StringLiteralConvertible : ExtendedGraphemeClusterLiteralConvertible {
typealias StringLiteralType

public init(stringLiteral value: Self.StringLiteralType)
}

public typealias StringLiteralType = String

可见StringLiteralConvertible协议继承自ExtendedGraphemeClusterLiteralConvertible协议:

public protocol ExtendedGraphemeClusterLiteralConvertible : UnicodeScalarLiteralConvertible {
typealias ExtendedGraphemeClusterLiteralType

public init(extendedGraphemeClusterLiteral value: Self.ExtendedGraphemeClusterLiteralType)
}

public typealias ExtendedGraphemeClusterType = String

ExtendedGraphemeClusterLiteralConvertible协议又集成自UnicodeScalarLiteralConvertible协议:

public protocol UnicodeScalarLiteralConvertible {
typealias UnicodeScalarLiteralType

public init(unicodeScalarLiteral value: Self.UnicodeScalarLiteralType)
}

public typealias UnicodeScalarType = String

因此,要实现字符串字面量就必须实现这三层协议栈中所有的方法:

extension Regex: StringLiteralConvertible {
public init(stringLiteral value: String) {
regexp = value
}

public init(extendedGraphemeClusterLiteral value: String) {
self = Regex(stringLiteral: value)
}

public init(unicodeScalarLiteral value: String) {
self = Regex(stringLiteral: value)
}
}

除非我们需要做一些细粒度的管理,比如字符串可能通过字形集群或Unicode标量创建,否则就像上面这样,直接使用字符串版本的实现即可。

实现了StringLiteralConvertible协议后,我们就可以这样创建Regex类型的变量:

let r: Regex = "^h..lo*!$"

如果变量的类型已经确定,事情就更简单了:

func findMatches(strings: [String], regex: Regex) -> [String] {
return strings.filter { regex.match($0) }
}

let matches = findMatches(["foo", "bar", "baz"], regex: "^b..")
print(matches)	// 输出结果:["bar", "baz"]

观察此前协议栈中三个协议的定义,他们都有一个类型别名:

typealias xxx

public typealias xxx = String

因此默认情况下通过字符串字面量创建的变量的类型都是String。如果你需要人为指定这个类型(在特定场合下可能性能更好),你可以重新指派类型别名:

typealias StringLiteralType = StaticString
let what = "hello"

print(what is StaticString)	// 输出结果:true
print(what is String)	// 输出结果:false