# 基本語法

Swift 是專為 iOS 和 OS X 應用程式開發工作所設計的一套全新的程式語言。然而，Swift 的許多部分，對於具備 C 和 Objective-C 開發經驗的你來說，是相當熟悉的。

Swift 針對 C 和 Objective-C 的所有基本型別，都提供了它自己的專屬版本，包括，整數的Int、浮點數值（floating-point value）的 Double 和 Float、布林值（Boolean）的 Bool，以及文字資料專用的 String。Swift 也提供了兩個主要集合（collection）型別的增強版本：Array 和 Dictionary，而相關描述請參考《集合型別》一節的內容。

就和 C 一樣，Swift 會使用變數來保存內容值，並以一個識別名稱來加以參照。Swift 還廣泛使用了內容值無法被更動的變數－也就是所謂的「常數」（constants），而且性能遠比 C 裡頭的常數還要強大許多。在 Switf 裡頭到處都會看到常數的蹤跡，因而使得程式碼變得更加安全，並且還能讓你在需要用到那些無須變更其內容值的意圖更加明確。

除了熟悉的型別以外，Swift 還採用了在 Objective-C 裡頭所沒有的進階型別。這裡頭包括了能讓你去建立，並傳遞整個內容值群組的「多元組」（tuples）。「多元組」可以讓多個值以一個單一複合值的形式從函數傳回。

Swift 還引入了「選擇性」（optional）型別，以便用來處理欠缺內容值的情況。「選擇性」代表目前是處於「這裡有個值，而且它等於 x」，或是「這裡完全沒有任何值」的其中一種情況。「選擇性」很類似在 Objective-C 裡頭搭配指標來使用 nil 的情況，但是它們可以被運用在任何型別上，而不只是只能用在類別上。「選擇性」會比 Objective-C 裡的 nil 指標更安全，也更具表達性，而且是屬於許多 Switf 的強大功能的重要關鍵。

「選擇性」可用來當作「Swift 是一種型別安全語言(type safe language)」的實證之一。Swift 會透過這個機制來協助你明確地表達，內容值是屬於你的程式碼可以進行處理的型別。假如你的程式碼期望處理的是一個 String 的話，型別安全性（type safety）會防止你錯誤地傳給它一個 Int。這項機制讓你可以在開發過程當中，盡可能提早捕捉到錯誤，以便加以修正。



## 常數與變數
常數與變數都會把一個特定型別的值（像是數值 10 或字串"Hello"）與一個名稱（例如，maximumNumberOfLoginAttempts  或 welcomeMessage）關連在一起。「常數」的值一旦被設定好就不能再被更動，而「變數」在未來的任何時候，都可以設定成一個不同的值。



### 常數與變數的宣告方式
常數與變數在它們被拿來使用之前，都必須先進行宣告（declare）。你會搭配關鍵字 let 來宣告常數，並使用關鍵字 var 來宣告變數。底下是一個用來示範常數和變數，可以被用來追蹤使用者試圖登入次數的範例：


	let maximumNumberOfLoginAttempts = 10
	var currentLoginAttempt = 0


這段程式碼可以被解讀成：

「宣告一個名為 maximumNumberOfLoginAttempts 的新常數，並賦予它一個 10 的內容值。然後，宣告一個名為 currentLoginAttempt 的新變數，並賦予它一個 0 的初始值。」

在這個範例當中，允許嘗試登入的最大次數被宣告成一個常數，因為最大值永遠都不會更動。目前試圖登入計數器是被宣告為一個變數，因為這個值必須在每次嘗試登入失敗後，就被遞增一次。

你可以在單一行裡頭，以逗號字元（,）分隔的方式，來同時宣告多個常數或變數：


	var x = 0.0, y = 0.0, z = 0.0


> 備註

> 假如在你的程式碼裡頭某個已保存的值，永遠不會再發生更動的話，通常可以使用關鍵字 let 來把它宣告為一個常數。只對需要能夠被進行更動其內容的值使用變數。



### 型別標註
你可以在宣告某個常數或變數時，提供一個「型別標註」（type annotation）來清楚的指出該常數或變數可以保存的內容值的型別。在常數或變數名稱後面放置一個冒號字元（:），再加上一個空白字元之後，接著再加上要使用的型別名稱，就可以編寫出一個型別標註資訊。

底下範例會對一個名為 welcomeMessage 的變數提供一個型別標註，以表示那個變數可以儲存型別 String 的值：


	var welcomeMessage: String


在宣告裡的冒號意思是「... 屬於型別 ...」，因此上述程式碼可以被解讀成：


「宣告一個屬於型別 String，且名為 welcomeMessage 的變數。」


片語「屬於型別  String」意思是「可以儲存任何 String 的值」。可以把它想成是能夠被保存的「內容型別」（或「內容類型」）的意思。

welcomeMessage 變數現在可以被設定成任何的字串值，而不會有錯誤發生：


	welcomeMessage = "Hello"


> 備註

> 實際上，你真的得去撰寫型別標註的情況並不多見。假如你在定義某個常數或變數時，去為它提供一個初始值的話，就如同《型別安全性與型別推斷》一節所描述的那樣，Swift 幾乎都能夠推斷出那個常數或變數所要使用的型別。在上述的 welcomeMessage 範例當中，由於沒有提供初始值，因此就得搭配一個型別標註來指定 welcomeMessage 的型別，而不是採取以初始值來進行推斷的方式。



### 常數與變數的命名方式
你幾乎可以使用任何你所喜歡的字元，甚至是 Unicode（通用碼）字元，來對你的常數和變數名稱進行命名：


	let π = 3.14159
	let 你好 = "你好世界"
	let 🐶🐮 = "dogcow"


常數和變數名稱，無法包含數學符號、箭頭、專用（private-use）或無效的 Unicode 碼位（code point），或者是畫線或畫框字元等等。此外，開頭的第一個字元不能使用數字字元，但是數字字元可以使用在名稱的其他位置上。

一旦你已經宣告某個特定型別的常數或變數，你就無法再以相同名稱去做重複宣告的動作，或者是改變它去儲存不同型別的內容值。此外，你不能夠把某個常數變更成變數，或者是把一個變數變更成常數。


> 備註

> 假如你需要以保留給 Swift 的關鍵字來當作某個常數或變數的名稱的話，你可以在使用它來當做名稱的時候，透過以反單引號字元（`）來圍住關鍵字的方式，即可達成這個目的。然而，你應該避免使用關鍵字來當作常數或變數的名稱，除非你真的已經別無選擇。


你可以把現有變數的值，更改成相容型別的另一個值。在底下範例當中，friendlyWelcome 的值會從 "Hello!" 變成了 "Bonjour!"：


	var friendlyWelcome = "Hello!"
	friendlyWelcome = "Bonjour!"
	// friendlyWelcome 現在是 "Bonjour!" 了


與變數所不同的是，常數的值只要被設定好，就不能再次被更動了。若試圖這樣做的話，你就會在進行程式碼的編譯作業時，得到一個錯誤訊息：


	let languageName = "Swift"
	languageName = "Swift++"
	// 這是一個編譯時期錯誤 - languageName 無法被進行更動



### 常數與變數的傾印方式
你可以搭配 println 函數來把常數或變數的目前內容值給傾印出來：


	println(friendlyWelcome)
	// 印出 "Bonjour!"


println 是一個全域函數，而它能夠把內容值以及隨後的一個斷行字元，給傾印成一個適當輸出結果，舉例來說，假如你正在使用 Xcode 的話，println 會把它的輸出給傾印到 Xcode 的主控台（console）面板當中（另一個函數 print 則會執行相同的處理作業，只是不會在內容值被印出的最後面，又另外附加一個斷行字元）。

println 函數會把你傳給它的任何 String 的內容值都給傾印出來：


    println("This is a string")
    // 印出 "This is a string"


println 函數可以運用類似 Cocoa 的 NSLog 函數的方式，來傾印出更複雜的日誌訊息（logging messages）。而這些訊息都可以引入常數和變數的目前內容值。

Swift 會使用「字串內插機制」（string interpolation），來把某個常數或變數的名稱當成一個保留位置給引入到某個較長的字串當中，以便提示 Swift 把它給替換成常數或變數的目前內容值。若要進行這項作業，你可以用一組小括弧來刮住名稱，並且在左括弧的前面，加入一個反斜線字元（\）來對它進行脫逸處理（escape）：


    println("The current value of friendlyWelcome is \(friendlyWelcome)")
    // 印出 "The current value of friendlyWelcome is Bonjour!"


> 備註

> 關於你可以用來搭配字串內插機制的所有選項，請參考《字串內插機制》一節內容。



## 註解
使用「註解」（comments）來把要當作筆記，或者用來提醒自己的不可執行文字，給引入到你的程式碼當中。註解會在你進行程式碼的編譯作業時，被 Swift 編譯器給忽略掉。

在 Swift 裡的註解內容，與 C 裡頭的註解文字非常類似。以兩個斜線字元（//）為首，即可標示出單行註解（single-line comments）：


	// 這是一行註解文字


你也可以透過以一個斜線字元緊接著一個星號字元（/*）的組合為開始，並以一個星號字元緊接著一個斜線字元（*/）的組合為結束的方式，來撰寫多行註解（multiline comments）：


	/* 這也是一段註解文字，
	但可以撰寫成好幾行內容 */


和 C 的多行註解所不同的是，Swift 裡的多行註解可以被套疊在其他的多行註解裡頭。你可以透過先展開一個多行註解區塊，然後在第一個區塊範圍裡頭，再展開第二個多行註解的方式，來撰寫出巢狀註解（nested comments）。在結束（關閉）第二個區塊範圍後，再結束第一個註解區塊：


	/* 這是第一個多行註解區塊的開始部分
	/* 這是第二個，也是被套疊在其中的多行註解 */
	這是第一個多行註解區塊的結尾部分 */


巢狀多行註解讓你即便是程式碼裡頭已經含有多行註解的情況下，仍然可以快速且輕易地將龐大的程式碼區塊範圍給註解起來。



## 分號字元（;）
和許多語言所不同的是，Swift 並不要求你一定得在程式碼裡的每個陳述式（statement）的後面，都加上一個分號字元（;），但你還是可以根據自己的習慣來加入這個分號字元。不過，假如你是想要把多個獨立陳述式給編寫在同一行裡頭的話，那就一定要在每個獨立陳述式的後面都加入分號字元：


	let cat = "🐱"; println(cat)
	// 印出 "🐱"



## 整數（Integers）
「整數」是像 42 和 -23 這類不帶有小數部分的純數字。整數可以是有號整數（正數、零，或負數），或者無號整數（正數或零）。

Swift 提供了 8 、16、32，和 64 位元形式的有號（signed）和無號（unsigned）整數。這些整數都遵循著與 C 類似的命名慣例－比如說，一個 8 位元無號整數就是屬於 UInt8 型別，而一個 32 位元有號整數，則是屬於 Int32 的型別。就和 Swift 裡的所有型別一樣，這些整數型別都有個以大寫字母為首的名稱。



### 整數範圍
你可以搭配 min 和 max 屬性來取得每個整數型別的最小值和最大值：


	let minValue = UInt8.min // minValue 等於 0，而且是屬於 UInt8 型別
	let maxValue = UInt8.max // maxValue 等於 255，而且是屬於 UInt8 型別


這些屬性的值都是屬於適當大小的數字型別（如同上述的 UInt8），而且都可被運用在帶有相同型別的其他數值的陳述式裡頭。



### Int
在大多數情況下，你並不需要在自己的程式碼裡頭，指出整數的特定大小。Swift 提供了一種額外的整數型別－Int 。而這個型別會與目前平台的原生詞組（word），擁有相同的尺寸大小：

* 在 32 位元平台上，Int 是與 Int32 擁有相同大小。

* 在 64 位元平台上，Int 是與 Int64 擁有相同大小。


除非你必須使用到特定的整數大小，否則通常只要對程式碼裡頭的整數使用 Int 即可。這有助於程式碼的一致性和互用性。以 32 位元平台來說，Int 可以保存在 -2,147,483,648 與 2,147,483,647 之間的任何數值，而這對許多整數範圍來說，已經相當夠用了。

### UInt
Swift也提供無號的整數型別，`UInt`，和目前平台原生詞組(word)有相同的大小

* 在 32 位元平台上，UInt 是與 UInt32 擁有相同大小。
* 在 64 位元平台上，UInt 是與 UInt64 擁有相同大小。

> 注意：
> 
只有在你需要儲存和目前平台原生字組(word)相同大小的無號整數時才使用UInt。否則建議使用Int，即使要儲存的值已知是非負數。統一使用Int有助程式的互用性，避免不同數字型別間需要轉換，且符合整數型別推斷，請參考型別安全和型別推斷

## 浮點數

浮點數是含有小數部份的數字，像是`3.141591`，`0.1`和`-273.15`。

浮點數可以表示的範圍遠比整數大很多，可以儲存遠大於或遠小於`Int`所能表示的數字。Swift提供兩種有號浮點數的型別

* `Double`表示64位元浮點數

* `Float`表示32位元浮點數

> 注意：
>
`Double`有至少小數點下15位的精確度，而`Float`有至少小數點下6位的精確度。選擇適當的浮點數型別取決於你的程式碼需要處理的數值範圍。當情況允許兩種型別時，建議使用`Double`。