程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> 深刻解析Swift中switch語句對case的數據類型婚配的支撐

深刻解析Swift中switch語句對case的數據類型婚配的支撐

編輯:更多關於編程

深刻解析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協定。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved