Swift 控制語句

來源:互聯網
上載者:User

標籤:

Control Flow指的是『邏輯控制語句』,包括if、if-else、for、for-in、while、do-while、switch等。其中大部分和OC中差不多,但Swift在某些方便增強了控制語句的功能。譬如for-in中引入..<...操作符;switch語句更是大不一樣了。本文也只針對for-in和switch語句展開闡述。

For-In

for-in語句基本上和OC中的for-in語句被太多區別,但新增了兩個符號:..<(類似於Python中的range())和...

  • ..<描述的區間是半閉區間(左閉右開),即0..<2表示[0,2)(0<=x<2,其中x為整數);
  • ...描述的區間是全閉區間(左閉右閉),即0...2表示[0,2](0<=x<=2,其中x為整數);

P.S:Swift剛開始推出來的時候,..<的原型是..,好在很快在後續版本中改成了..<,否則實在是個災難!看著一門語言一點點進步,最後發展成一門偉大的語言是一件挺棒的事情,Swift會發展成一門偉大的語言嗎?我想會!
P.S:我個人覺得...不是一個很好的設計,為什麼要這麼一個操作符呢?希望以後能找到答案吧!

Switch

Switch語句和if語句都屬於條件陳述式,switch會嘗試把某個值與若干個模式(pattern)進行匹配。根據第一個匹配成功的模式,switch語句會執行對應的代碼。當有可能的情況較多時,通常用switch語句替換if語句,如下:

switch someValueToConsider {case value1:// respond to value1case value2, value3:// respond to value2 or value3default:// otherwise, do something else}

switch語句都由多個case構成。為了匹配某些更特定的值,Swift提供了幾種更複雜的匹配模式,這些模式將在本節的稍後部分提到。

Swift規定switch語句必須是「完備的」。這就是說,每一個可能的值都必須至少有一個case塊與之對應。在某些不可能涵蓋所有值的情況下,你可以使用預設default塊滿足該要求,這個預設塊必須在switch語句的最後面。

不存在隱式fallthrough

在C和OC中,寫switch語句時,一定要確保在每個case語句的末尾添加一句break;,這樣才能確保switch代碼塊終止,否則會執行下一個case/default塊,這種行為在Swift中被稱為「fallthrough」。

與C語言和OC中的switch語句不同,在Swift中,當匹配的case塊中的代碼執行完畢後,程式會自動終止switch語句,而不會繼續執行下一個case塊。這也就是說,不需要在case塊中顯式地使用break語句,這使得switch語句更安全、更易用,也避免了因忘記寫break語句而產生的錯誤。

除此之外,Swift還規定每一個case語句中都必須包含至少一條語句,像下面這樣書寫代碼是無效的,因為第一個case塊是空的:

let anotherCharacter: Character = "a"switch anotherCharacter {case "a":case "A":println("The letter A")default:println("Not the letter A")}// this will report a compile-time error

一個case也可以包含多個匹配模式,不同的pattern用逗號,分開。

範圍匹配

case塊的pattern可以是一個範圍,如下:

let count = 3_000_000_000_000let countedThings = "stars in the Milky Way"var naturalCount: Stringswitch count {case 0:naturalCount = "no"case 1...3:naturalCount = "a few"case 4...9:naturalCount = "several"case 10...99:naturalCount = "tens of"case 100...999:naturalCount = "hundreds of"case 1000...999_999:naturalCount = "thousands of"default:naturalCount = "millions and millions of"}println("There are \(naturalCount) \(countedThings).")// prints "There are millions and millions of stars in the Milky Way."
元組

你可以使用元組在同一個switch語句中測試多個值。元組中的元素可以是值,也可以是範圍。另外,使用底線_來匹配所有可能的值,如下例子展示了如何使用(Int, Int)類型的元組來分類中的點(x, y)

let somePoint = (1, 1)switch somePoint {case (0, 0):println("(0,0) is at the origin")case (_, 0):println("(\(somePoint.0), 0) is on the x-axis")case (0, _):println("(0, \(somePoint.1)) is on the y-axis")case (-2...2, -2...2):println("(\(somePoint.0), \(somePoint.1)) is inside the box")default:println("(\(somePoint.0), \(somePoint.1)) is outside of the box")}// prints "(1, 1) is inside the box"

 

                                                                  

在上面的例子中,switch 語句會判斷某個點是否是原點(0, 0),是否在紅色的x軸上,是否在黃色y軸上,是否在一個以原點為中心的4x4的矩形裡,或者在這個矩形外面。

不像C語言,Swift允許多個case匹配同一個值。實際上,在這個例子中,點(0, 0)可以匹配所有四個case。但是,如果存在多個匹配,那麼只會執行第一個被匹配到的case塊。考慮點(0, 0)會首先匹配case (0, 0),因此剩下的能夠匹配(0, 0)的case塊都會被忽視掉。

Value Bindings

在多個值匹配(使用tuple)時,我們常常會需要用到被檢測值的局部值,switch語句還允許在case中進行value binding,如下:

let anotherPoint = (2, 0)switch anotherPoint {case (let x, 0):println("on the x-axis with an x value of \(x)")case (0, let y):println("on the y-axis with an y value of \(y)")case (x, y):println("somewhere else at (\(x), \(y))")}// prints "on the x-axis with an x value of 2"

這個例子中,switch語句會判斷某個點是否在x軸和y軸上,或者在別的地方。

Where語句

Swift中還有一個關鍵字where,常用來處理更複雜的模式比對;在case中使用where關鍵字引導的where語句可以用來判斷額外的條件:

let yetAnotherPoint = (1, -1)switch yetAnotherPoint {case let (x, y) where x == y:println("\(x), \(y) is on the line x == y")case let (x, y) where x == -y:println("\(x), \(y) is on the line x == -y")case let (x, y):println("\(x), \(y) is just some arbitrary point")}

這個例子中,switch語句會判斷某個點是否在綠線(y=x)上,是否在紫線(y=-x)上,或者不在對角線上。

控制轉移語句

控制轉移代碼能改變你代碼的執行順序,通過它你可以控制碼的跳轉,在Swift中,有四種控制轉移語句:

  • continue
  • break
  • fallthrough
  • return

除此之外,Swift還引入「labeled statements」,用來協助更靈活的控制轉移。

continue、break、return這幾個控制語句與我們在C、OC中所瞭解的控制語句相比沒啥不同,這裡就不贅述了;所以本節內容包括:

  • switch與break;
  • switch與fallthrough;
  • labeled statements;
switch與break

上文已經提到,在C和OC中,常常需要在case塊後面添加break;代碼,因為如果不這樣,switch語句就緊接著執行後續的case語句(注意,後續的case pattern可不會被檢查啊,而是直接執行後續case的body代碼);但在Swift中,不需要這樣,因為在Swift的switch語句中,當匹配的case塊中的代碼執行完畢後,程式會自動終止switch語句,而不會繼續執行下一個case塊。

所以按理說是不需要在switch語句中顯式使用break指令的。但事實並非這樣,因為Swift還有一個要求,規定每一個case語句中都必須包含至少一條語句。然而,在某些情況下的某些case分支裡,可能真的啥都不想幹,其他語言使用;了事,但Swift語句中不需要使用;,此時一般使用break語句代替,如下:

let numberSymbol: Character = "三" // Simplified Chinese for the number 3var possibleIntegerValue: Int?switch numberSymbol {case "1", "?", "一", "?":possibleIntegerValue = 1case "2", "?", "二", "?":possibleIntegerValue = 2case "3", "?", "三", "?":possibleIntegerValue = 3case "4", "?", "四", "?":possibleIntegerValue = 4default:break}
fallthrough

本節簡單談談fallthrough,這可是新玩意兒。

上文已經多次提及,Swift語言中的switch不會從上一個case分支落入到下一個case分支中。相反,只要第一個匹配到的case分支完成了它需要執行的語句,整個switch代碼塊完成了它的執行。相比之下,C語言要求你顯示的插入break語句到每個switch分支的末尾來阻止自動落入到下 一個case分支中。Swift語言的這種避免預設落入到下一個分支中的特性意味著它switch功能要比C語言的更加清晰和可預測,可以避免無意識地執行多個case分支從而引發的錯誤。

但有時候確實需要人為的fallthrough,此時fallthrough關鍵字就派上用場了,如下:

let integerToDescribe = 5var description = "The number \(integerToDescribe) is"switch integerToDescribe {case 2, 3, 5, 7, 11, 13, 17, 19:description += "a prime number, and also"fallthroughdefault:description += " an integer"}println(description)// prints "The number 5 is a prime number, and also an integer."

值得一提的是,fallthrough關鍵字不會檢查它下一個將會落入執行的case中的匹配條件。fallthrough簡單地使代碼執行繼續串連到下一個case中的執行代碼,這和C語言標準中的switch語句特性是一樣的。

Labeled Statements

在Swift語言中,你可以在迴圈體(for迴圈或while迴圈)和switch代碼塊中嵌套迴圈體和switch代碼塊來創造複雜的控制流程結構。然而,迴圈體和switch代碼塊兩者都可以使用break 語句來提前結束整個代碼塊。因此,顯示地指明break語句想要終止的是哪個迴圈體或者switch代碼塊會很有用。類似地,如果你有許多嵌套的迴圈體,顯示指明continue語句想要影響哪一個迴圈體也會非常有用。

為了實現這個目的,你可以使用標籤來標記一個迴圈體或者switch代碼塊,當使用break或者continue時,帶上這個標籤,可以控制該標籤代表對象的中斷或者執行。

產生一個帶標籤的語句是通過在該語句的關鍵詞的同一行前面放置一個標籤,並且該標籤後面還需帶著一個冒號。下面是一個while迴圈體的文法,同樣的規則適用於所有的迴圈體和switch代碼塊:

labelName: while condition {// statements}

label的使用非常簡單,如下有一段代碼示範了label的應用:

gameLoop: while square != finalSquare {if ++diceRoll == 7 { diceRoll = 1 }switch square + diceRoll {case finalSquare:// diceRoll will move us to the final square, so the game is overbreak gameLoopcase let newSquare where newSquare > finalSquare:// diceRoll will move us beyond the final square, so roll againcontinue gameLoopdefault:// this is a valid move, so find out its effectsquare += diceRollsquare += board[square]}}println("Game over!")

顯然,labeled statements可以實作類別似於C語言中goto語句的功能。

Swift 控制語句

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.