深刻解析Swift中switch語句對case的數據類型婚配的支撐。本站提示廣大學習愛好者:(深刻解析Swift中switch語句對case的數據類型婚配的支撐)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻解析Swift中switch語句對case的數據類型婚配的支撐正文
Swift可以對switch中分歧數據類型的值作婚配斷定:
var things = Any[]() things.append(0) things.append(0.0) things.append(42) things.append(3.14159) things.append("hello") things.append((3.0, 5.0)) things.append(Movie(name:"Ghostbusters", director:"Ivan Reitman")) for thing in things { switch thing { case 0 as Int: println("zero as an Int") case 0 as Double: println("zero as a Double") case let someInt as Int: println("an integer value of (someInt)") case let someDouble as Double where someDouble > 0: println("a positive double value of (someDouble)") case is Double: println("some other double value that I don't want to print") case let someString as String: println("a string value of "(someString)"") case let (x, y) as (Double, Double): println("an (x, y) point at (x), (y)") case let movie as Movie: println("a movie called '(movie.name)', dir. (movie.director)") default: println("something else") } } // zero as an Int // zero as a Double // an integer value of 42 // a positive double value of 3.14159 // a string value of"hello" // an (x, y) point at 3.0, 5.0 // a movie called 'Ghostbusters', dir. Ivan Reitman
這外面會依據thing的值停止婚配,到對應的case傍邊。
明天忽然想到一個成績,讓我認為有需要總結一下switch語句。我們曉得swift中的switch,遠比C說話只能比擬整數壯大很多,但成績來了,哪些類型可以放到switch中比擬呢,對象可以比擬麼?
官方文檔對switch的用法給出了如許的說明:
Cases can match many different patterns, including interval matches, tuples, and casts to a specific type.
也就是說除最經常使用的比擬整數、字符串等等以外,switch還可以用來婚配規模、元組,轉化成某個特定類型等等。但文檔裡這個including用的其實是無語,由於它沒有指明一切可以放在switch中比擬的類型,文章開首提出的成績仍然沒有謎底。
我們無妨著手試一下,用switch婚配對象:
class A { } var o = A() var o1 = A() var o2 = A() switch o { case o1: print("it is o1") case o2: print("it is o2") default: print("not o1 or o2") }
果真,編譯器報錯了:“Expression pattern of type 'A' cannot match values of type 'A'”。至多我們今朝還不明確“expression pattern”是甚麼,怎樣類型A就不克不及婚配類型A了。
我們做一下修改,在case語句前面加上let:
switch o { case let o1: print("it is o1") case let o2: print("it is o2") default: print("not o1 or o2") }
OK,編譯運轉,成果是:it is o1。這是由於case let不是婚配值,而是值綁定,也就是把o的值賦給暫時變量o1,這在o是可選類型時很有效,相似於if let那樣的隱式解析可選類型。沒有打出it is o2是由於swift中的switch,只婚配第一個符合的case,然後就停止了,即便不寫break也不會跳到前面的case。
扯遠了,回到話題下去,既然添加let不可,我們得想其余方法。這時候候無妨斟酌一下switch語句是怎樣完成的。據我小我猜想,估量相似於用了很多多少個if斷定有無婚配的case,那既然如斯,我們給類型A重載一下==運算符嘗嘗:
class A {} func == (lhs: A, rhs: A) -> Bool { return true } var o = A(); var o1 = A() ;var o2 = A() switch o { case o1: print("it is o1") case o2: print("it is o2") default: print("not o1 or o2") }
很明顯,又掉敗了。假如這就可以弄定成績,那這篇文章也太水了。報錯信息和之前一樣。可成績是我們曾經重載了==運算符,為何A類型照樣不克不及餓婚配A類型呢,豈非switch不消斷定兩個變量能否相等麼。
switch作為一個多前提婚配的語句,天然是要斷定變量能否相等的,不外它不是經由過程==運算符斷定,而是經由過程~=運算符。再來看一段官方文檔的說明:
An expression pattern represents the value of an expression. Expression patterns appear only in switch statement case labels.
和這句話:
The expression represented by the expression pattern is compared with the value of an input expression using the Swift standard library ~= operator.
第一句說明了之前的報錯,所謂的“express pattern”是指表達式的值,這個概念只在switch的case標簽中有。所以之前的報錯信息是說:“o1這個表達式的值(照樣o1)與傳入的參數o都是類型A的,但它們沒法婚配”。至於為何不克不及婚配,謎底在第二句話中,由於o1和o的婚配是經由過程挪用尺度庫中的~=運算符完成的。
所以,只需把重載==換成重載~=便可以了。修改一個字符,其余都不消改,然後法式便可以運轉了。Swift默許在~=運算符中挪用==運算符,這也就是為何我們感到不到婚配整數類型須要甚麼額定處置。但關於自界說類型來講,不重載~=運算符,就算你重載了==也是沒用的。
除此之外,還有一種處理辦法,那就是讓A類型完成Equatable協定。如許就不須要重載~=運算符了。謎底就在Swift的module的最初幾行:
@warn_unused_result public func ~=<T : Equatable>(a: T, b: T) -> Bool
Swift曾經為一切完成了Equatable協定的類重載了~=運算符。固然完成Equatable協定只需求重載==運算符,但假如你不顯式的注明遵照了Equatable協定,swift是沒法曉得的。是以,假如你重載了==運算符,就隨手標注一下完成了Equatable協定吧,如許還有許多利益,好比SequenceType的split辦法等。
最初總結一句:
能放在switch語句中的類型必需重載~=運算符,或許完成Equatable協定。