在 swift 當中,switch
並不像 objc 一樣只能對整型或列舉進行匹配。
事實上,我們可以使用switch
對很多態別進行匹配,包括(但不僅限於)元組。
let point = cgpoint(x: 7, y: 0)
switch (point.x, point.y)
還有一點要注意的是,switch
是按case
模式被指定的順序來判斷求值的,並且它會在匹配到第乙個滿足的case
後跳出。與 c 和 objective-c 不同,我們不需要使用break
關鍵字1。
這意味著在上面的**中,如果座標是(0, 0)
,則它會匹配第乙個case
列印出"on the origin!"
,並就此打住,就算(0, _)
和(_, 0)
也符合匹配的條件,它也不會再去進行匹配。因為它已經在第乙個匹配之後跳出了。
為什麼要止步於元組呢?在 swift 當中,我們也可以使用switch
來對很多原生型別進行匹配,包括字串和字元,比如:
let car: character = "j"
switch car
可以注意到,我們可以使用按逗號分隔的多個模式來進行匹配,使符合這些模式的匹配(這裡是匹配所有的母音字母)都執行同一段**。這可以避免我們寫很多重複的**。
range 在模式匹配中也很有用。提醒一下,range
是乙個泛型型別,它包含了t
型別的start
和end
成員,同時t
必須是乙個forwardindextype
。這包括int
和character
在內的許多態別。
?我們可以使用那麼我們如何在range(start: 1900, end: 2000)
來顯式地宣告乙個 range,也可以使用語法糖操作符..<
(不包含最後乙個數end
)或...
(包含最後乙個數end
),所以我們也可以將上面的 range 寫為1900..<2000
(更方便也更易讀)
switch
當中使用它們呢?其實相當簡單,在case
模式中使用 range 來判斷值是否落於這個範圍內!
let count = 7
switch count
可以看到我們在case
當中混用了int
整型值與range
的值。這樣的使用並沒有任何問題,只要我們保證覆蓋了所有可能的情況。
雖說int
是最常用的 range 型別,我們也可以使用其它的forwardindextype
型別,包括...character
!還記得上面寫的**麼?它有一點問題,那就是對於標點符號以及其它不是a-z
的字元,它也會列印出 "consonant"。讓我們來解決這個問題2(同時也增加了小寫字母):
func chartype(car: character) -> string
}print("jules verne".characters.map(chartype))
// ["consonant", "vowel", "consonant", "vowel", "consonant", "other", "consonant", "vowel", "consonant", "consonant", "vowel"]
至此一切順利,但我們能不能更進一步呢?答案是當然沒問題:讓我們把模式匹配用在... 型別上!
在這裡,我們定義了三個結構體,並遵守相同的協議:
protocol medium
}struct book: medium
struct movie: medium
struct website: medium
// and an array of media to switch onto
let media: [medium] = [
book(title: "20,000 leagues under the sea", author: "jules vernes", year: 1870),
movie(title: "20,000 leagues under the sea", director: "richard fleischer", year: 1955)
]
然後我們要如何對medium
使用switch
的模式匹配,讓它對book
和movie
做不同的事呢?簡單,在模式匹配中使用as
和is
!
for medium in media
}
注意到對book
和movie
使用的as
,我們需要確定它們是不是特定的型別,如果是,則將它們轉換後的型別賦值給乙個常量(let b
或let m
),因為我們之後要使用到這個常量3。
而另一方面,對website
我們只使用了is
,因為我們只需要檢查medium
是不是乙個website
型別,如果是,我們並沒有對它進行轉換與儲存在常量中(我們不需要在print
語句中使用到它)。這與使用case let _as website
有點類似,因為我們只關心它是不是website
型別,而不需要它的物件的值。
?注意:如果必須在在接下來的部分,我們會學習如何建立可以直接使用於模式匹配的自定義型別,探索更多的語法糖,並看到如何在swtich
匹配中使用到as
和is
,這裡有可能存在**異味,比如,在上面這個特定的例子中,在protocol medium
當中新增乙個releaseinfo: string
屬性就比使用switch
來對不同的型別進行匹配要好。
switch
語句之外使用模式匹配,以及更加複雜的匹配表示式... 迫不及待了吧!
可以使用fallthrough
關鍵字來讓求值判斷流向下乙個case
。但是在實踐上要使用到這個關鍵字的場景很少,並不經常會碰到。
當然,這種字串的分析方法並不是最好的,也不是值得推薦的 —— 因為 unicode 字元以及本地化都比這複雜得多。所以類似這樣的功能我們更應該使用nscharacterset
,考慮當前的nslocale
把哪些字母定義為母音(「y」 是母音嗎?還有 「õ」 or 「ø」 呢?),等等。不要把這個例子看得太認真,我只是用它來展示switch
+range
的強大而已。
儘管與if let b = medium as? book
表示式很相似 —— 當medium
可以被轉換為特定型別的時候,它們都將其繫結到乙個變數上 —— 但是在模式匹配中我們要使用as
而非as?
。儘管它們的機制很相似,但是它們的語義是不同的(「嘗試進行型別轉換,如果失敗就返回nil
」 vs 「判斷這個模式是不是匹配這種型別」)。
第二彈 getch getchar和gets
緩衝輸入函式,函式只有在滿足輸入次數要求的前提下,遇到回車時才結束輸入,之前所有的字元都會逐個顯示在螢幕上,但是只有第乙個字元返回乙個ascii碼。具體的過程就是getchar 被呼叫時,程式就等著使用者按鍵,且將使用者輸入的字元依次回顯到螢幕,使用者必須摁完規定的次數 迴圈語句 即使是回車也要摁 ...
PHP高階(第二彈 類和物件)
類是物件導向程式設計的基本概念,php中也有類和物件的概念。比如定義乙個汽車類 定義乙個類 class car 受保護的屬性與私有屬性不允許外部呼叫,在類的成員方法內部是可以呼叫的。public function getprice 物件通過new關鍵字進行例項化 car new car 也可以採用變...
C Light 和 uLua的對比第二彈
上次的對比大家還有印象否,c light和ulua對比各有勝負 今天我們加入乙個去反射優化,這是ulua沒辦法實現的優化,我們也就只能不要臉的勝之不武了 以原生執行同一測試時間為x1,數字越小的越快 專案ulua c light c light 去反射優化 效能測試一 x4.5 x4.5 x2.19...