Swift 中 Literal 可以這么用,你造嗎?

簡評:看看這段 Swift 代碼:
let link:LinkedList = [1,2,3,4,5,6,7,8]
link 并不是一個數組哦,看完這篇文章你就懂了。

自2012年以來,可以使用 “literal” 表達式初始化NSDictionary,NSArray,NSNumber或NSString。

NSNumber *numb = @1;
NSArray *things = @[@3,@45,@65];
NSDictionary *map = @{@"Florida" : @1 , @"Nevada" : @6 };
NSString *greet = @"Hello there!";

這種 “literal” 表達式讓代碼變得更加簡潔。

你有沒有想過使用 “literal” 表達式來初始化自己的數據結構。

Swift 中提供了 “ExpressibleBy _____” 這類協議:

  • 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

可以使用 “literal” 表達式來初始化自己的數據結構,可以看看下面的例子,如何使用 “literal” 表達式來構建自己的數據結構。

Array-ish 數據結構

來看看 Swift 中的例子, [1,2,3,4,5,6,7,8] 這很可能用于初始化一個 Array。但是!他也可以用于初始化成其他的數據結構。

鏈表

下面這段代碼就是介紹如何使用 Array literal 來初始化一個鏈表:

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 類遵從 ExpressibleByArrayLiteral 協議,實現 init(arrayLiteral: Self.Element...) 這個初始化方法, 那么我們就可以直接使用 Array literal 賦值進行初始化。

let link:LinkedList<Int> = [1,2,3,4,5,6,7,8] 

注意:必須使用 Array literal 來賦值,而不能用一個數組賦值,因為這是兩個不同的東西,例如:

let someArray = [1,2,3,4]
let list:LinkedList<Int> = someArray  // 這段代碼會報錯。

堆棧

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)
    }
}

隊列

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 初始化可以提高可讀性。這種方法適用于樹或有向圖嗎?我把這個探索留給了讀者 : ) Happy Hacking!

原文:Express Yourself Swift Style

推薦閱讀:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • 關于 Swift 重要這個文檔所包含的準備信息, 是關于開發的 API 和技術的。這個信息可能會改變, 根據這個文...
    無灃閱讀 4,355評論 1 27
  • 首先安裝Firebird,官網下個pkg裝一下就好了。 然后創建Firebird鏈接,為后面編譯interbase...
    zidaneno5閱讀 989評論 0 1
  • 快速提升 前面提到有關于學習能力的話題,既然你選擇了程序員這個行業,就得接受在將來的日子里保持持續學習的狀態,軟件...
    楚秀才閱讀 293評論 0 1