簡(jiǎn)評(píng):看看這段 Swift 代碼:
let link:LinkedList = [1,2,3,4,5,6,7,8]
link 并不是一個(gè)數(shù)組哦唆涝,看完這篇文章你就懂了。
自2012年以來(lái)唇辨,可以使用 “l(fā)iteral” 表達(dá)式初始化NSDictionary廊酣,NSArray,NSNumber或NSString赏枚。
NSNumber *numb = @1;
NSArray *things = @[@3,@45,@65];
NSDictionary *map = @{@"Florida" : @1 , @"Nevada" : @6 };
NSString *greet = @"Hello there!";
這種 “l(fā)iteral” 表達(dá)式讓代碼變得更加簡(jiǎn)潔亡驰。
你有沒(méi)有想過(guò)使用 “l(fā)iteral” 表達(dá)式來(lái)初始化自己的數(shù)據(jù)結(jié)構(gòu)。
Swift 中提供了 “ExpressibleBy _____” 這類(lèi)協(xié)議:
- Expressible By Array Literal
- Expressible By Boolean Literal
- Expressible By Dictionary Literal
- Expressible By Float Literal
- Expressible By Integer Literal
- Expressible By String Literal
- Expressible By Unicode Scalar Literal
- Expressible By Extended Grapheme Cluster Literal
可以使用 “l(fā)iteral” 表達(dá)式來(lái)初始化自己的數(shù)據(jù)結(jié)構(gòu)嗡贺,可以看看下面的例子隐解,如何使用 “l(fā)iteral” 表達(dá)式來(lái)構(gòu)建自己的數(shù)據(jù)結(jié)構(gòu)。
Array-ish 數(shù)據(jù)結(jié)構(gòu)
來(lái)看看 Swift 中的例子诫睬, [1,2,3,4,5,6,7,8] 這很可能用于初始化一個(gè) Array。但是帕涌!他也可以用于初始化成其他的數(shù)據(jù)結(jié)構(gòu)摄凡。
鏈表
下面這段代碼就是介紹如何使用 Array literal 來(lái)初始化一個(gè)鏈表:
class LinkedList<T> : ExpressibleByArrayLiteral, CustomDebugStringConvertible {
var debugDescription: String {
get {
var accum = ""
guard let startNode = self.head else { return "(empty list)" }
accum += startNode.debugDescription
var currentNode:Node = startNode
while(true) {
guard let node = currentNode.next else { break }
accum += node.debugDescription
currentNode = node
}
return accum
}
}
var head:Node?
var tail:Node?
typealias Element = T
required public init(arrayLiteral elements:Element...) {
for i in elements {
if self.head == nil {
self.head = Node(data:i)
self.tail = self.head
continue
}
let newNode = Node(data:i)
self.tail?.next = newNode
self.tail = newNode
}
}
class Node : CustomDebugStringConvertible {
var debugDescription: String {
get {
var accum = "(\(data))->"
if next == nil {
accum += "*"
}
return accum
}
}
var next:Node?
var data:T
init(data:T) {
self.data = data
}
}
}
let link:LinkedList<Int> = [1,2,3,4,5,6,7,8]
print(link) // Prints (1)->(2)->(3)->(4)->(5)->(6)->(7)->(8)->*
LinkedList 類(lèi)遵從 ExpressibleByArrayLiteral 協(xié)議续徽,實(shí)現(xiàn) init(arrayLiteral: Self.Element...) 這個(gè)初始化方法, 那么我們就可以直接使用 Array literal 賦值進(jìn)行初始化亲澡。
let link:LinkedList<Int> = [1,2,3,4,5,6,7,8]
注意:必須使用 Array literal 來(lái)賦值钦扭,而不能用一個(gè)數(shù)組賦值,因?yàn)檫@是兩個(gè)不同的東西床绪,例如:
let someArray = [1,2,3,4]
let list:LinkedList<Int> = someArray // 這段代碼會(huì)報(bào)錯(cuò)客情。
堆棧
struct ConvertibleStack<T> : ExpressibleByArrayLiteral, CustomDebugStringConvertible {
var debugDescription: String {
get {
return "Stack: \(storage)"
}
}
typealias Element = T
private var storage: [T] = []
public init(arrayLiteral elements:Element...) {
self.storage = elements
}
mutating func push(item:T) {
storage.insert(item, at: 0)
}
mutating func pop() -> T? {
guard storage.count > 0 else { return nil }
return storage.remove(at: 0)
}
}
隊(duì)列
struct ConvertibleStack<T> : ExpressibleByArrayLiteral, CustomDebugStringConvertible {
var debugDescription: String {
get {
return "Stack: \(storage)"
}
}
typealias Element = T
private var storage: [T] = []
public init(arrayLiteral elements:Element...) {
self.storage = elements
}
mutating func push(item:T) {
storage.insert(item, at: 0)
}
mutating func pop() -> T? {
guard storage.count > 0 else { return nil }
return storage.remove(at: 0)
}
}
最后,如果正確的使用 litera 初始化可以提高可讀性癞己。這種方法適用于樹(shù)或有向圖嗎膀斋?我把這個(gè)探索留給了讀者 : ) Happy Hacking!
推薦閱讀:
- Swift 的 Enums 是 “Sum” 類(lèi)型,這讓一切變得更有趣
- 極光開(kāi)源項(xiàng)目:「Aurora UI」痹雅,一個(gè)通用 IM 聊天 UI 組件仰担,首版即支持 swift。