第二章 - 無所不能的Extension

[表二] Objective-C (Category) 與 Swift (Extension) 的比較 table 2

  • Extension 等價於 Objective-CCategory
  • Category 只能作用於 ClassExtension 則是所有看得到的型別皆可擴充。
  • Extension 的語法,較 Objective-C 更為簡單易寫。

基本的 Extension 使用方式

import Foundation

extension NSURL {
    func getParams()->[String:String]{

        let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)

        //取出items,如果為nil就改為預設值 空陣列
        let queryItems = components?.queryItems ?? []

        return queryItems.reduce([String:String](), combine: { (var dict, item) -> [String:String] in
            dict[item.name] = item.value ?? ""
            return dict
        })

    }
}

let url = NSURL(string: "http://host/?first=grady&last=zhuo&github=1")
url?.getParams()

對現有型態進行擴充

extension Int {
    func repeats(word:String)->[String]{
        return [String](count: self, repeatedValue: word)
    }
}

//可以像script語言,直接對著數字做一些動作。
3.repeats("1")

對泛型 Type 進行擴充

extension Array where  Element : Hashable {

    func combineHashString()->String{

        /*
        var result = ""
        for element in self {
            result += "\(element.hashValue)"
        }
        */

        return self.reduce("", combine: { (str, element) -> String in
            return str + "\(element.hashValue)"
        })
    }

}


let stringArray = ["Hello world", "My name is Grady"]
stringArray.combineHashString()

Extend 時,實作指定 protocol

//制作Dog 的 struct, 並只包括 name
struct Dog {
    var name:String
}

//產生 dog 的 instance
let dog = Dog(name: "Money")
//一開始dog沒有hashValue
//dog.hashValue

//extend Dog 並 實作 Hashable 的 protocol
extension Dog : Hashable {

    //protocol Hashable需實作的hashValue getter
    var hashValue: Int {
        return self.name.hashValue
    }
}

// Hashable因繼承自 protocol Equtable,所以需要實作 == 運算子所要處理的運算
func ==(lhs: Dog, rhs: Dog)->Bool{
    return lhs.hashValue == rhs.hashValue
}

本章練習 - Practice

Objective-C裡幾乎所有Class皆繼承自NSObject,因此所有的instance幾乎都有descritpiondebugDescription的property可以呼叫並覆寫,以自定義這物件裡轉為字串描述的依據,但Swift已預設無此機制。

現在有一個Person的Struct, 請幫Person加上descritpion的參數, 讓enoch右邊的顯示可以出現 跟 grady的顯示結果相同,但名字是依照輸入名字而變化 "(Person) name: Enoch, age: 18"

[提示] 有專門的Protocol可以實作喔。

let grady = Grady() //(Person) name: Grady, age: 18
let enoch = Person(age: 18, name: "Enoch")

results matching ""

    No results matching ""