第七章——字串(字串字面量轉換)

bestswifter發表於2017-12-27

本文系閱讀閱讀原章節後總結概括得出。由於需要我進行一定的概括提煉,如有不當之處歡迎讀者斧正。如果你對內容有任何疑問,歡迎共同交流討論。

建立字串變數有兩種寫法: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
複製程式碼

相關文章