天天看點

Swift 基礎之類型

Swift 基礎之類型

一:類型安全和類型推測

Swift 是一個類型安全(typesafe)的語言。類型安全的語言可以讓你清楚地知道代碼要處 理的值的類型。如果你的代碼需要一個 String,你絕對不可能不小心傳進去一個 Int。

由于 Swift 是類型安全的,是以它會在編譯你的代碼時進行類型檢查(type checks),并把 不比對的類型标記為錯誤。這可以讓你在開發的時候盡早發現并修複錯誤。

當你要處理不同類型的值時,類型檢查可以幫你避免錯誤。然而,這并不是說你每次聲明 常量和變量的時候都需要顯式指定類型。如果你沒有顯式指定類型,Swift 會使用類型推測(type inference)來選擇合适的類型。有了類型推測,編譯器可以在編譯代碼的時候自動 推測出表達式的類型。原理很簡單,隻要檢查你賦的值即可。

因為有類型推測,和 C 或者 Objective-C 比起來 Swift 很少需要聲明類型。常量和變量 雖然需要明确類型,但是大部分工作并不需要你自己來完成。

當你聲明常量或者變量并賦初值的時候類型推測非常有用。當你在聲明常量或者變量的時 候賦給它們一個字面量(literalvalue 或 literal)即可觸發類型推測。(字面量就是會直接出現在你代碼中的值,比如 42 和 3.14159。)

例如,如果你給一個新常量指派 42 并且沒有标明類型,Swift 可以推測出常量類型是 Int,因為你給它賦的初始值看起來像一個整數:

let meaningOfLife = 42
// meaningOfLife 會被推測為 Int 類型           

複制

同理,如果你沒有給浮點字面量标明類型,Swift 會推測你想要的是 Double:

let pi = 3.14159
// pi 會被推測為 Double 類型           

複制

當推測浮點數的類型時,Swift 總是會選擇 Double 而不是 Float。

如果表達式中同時出現了整數和浮點數,會被推測為 Double 類型:

let anotherPi = 3 + 0.14159
// anotherPi 會被推測為 Double 類型           

複制

原始值 3 沒有顯式聲明類型,而表達式中出現了一個浮點字面量,是以表達式會被推測為Double 類型。

二:數值型類型轉換

通常來講,即使代碼中的整數常量和變量已知非負,也請使用 Int 類型。總是使用預設的整數類型可以保證你的整數常量和變量可以直接被複用并且可以比對整數類字面量的類型 推測。隻有在必要的時候才使用其他整數類型,比如要處理外部的長度明确的資料或者為 了優化性能、記憶體占用等等。使用顯式指定長度的類型可以及時發現值溢出并且可以暗示正在處理特殊資料。

1. 整數轉換

不同整數類型的變量和常量可以存儲不同範圍的數字。Int8 類型的常量或者變量可以存儲 的數字範圍是-128~127,而 UInt8 類型的常量或者變量能存儲的數字範圍是 0~255。如果 數字超出了常量或者變量可存儲的範圍,編譯的時候會報錯:

let cannotBeNegative: UInt8 = - 1
// UInt8 類型不能存儲負數,是以會報錯
let tooBig: Int8 = Int8.max + 1
// Int8 類型不能存儲超過最大值的數,是以會報錯           

複制

由于每中整數類型都可以存儲不同範圍的值,是以你必須根據不同情況選擇性使用數值型類型轉換。這種選擇性使用的方式,可以預防隐式轉換的錯誤并讓你的代碼中的類型轉換意圖變得清晰。

要将一種數字類型轉換成另一種,你要用目前值來初始化一個期望類型的新數字,這個數 字的類型就是你的目标類型。在下面的例子中,常量 twoThousand 是 UInt16 類型,然而 常量 one 是 Uint8 類型。它們不能直接相加,因為它們類型不同。是以要調用 UInt16(one)來建立一個新的 UInt16 數字并用 one 的值來初始化,然後使用這個新數字來計算:

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + UInt16(one)           

複制

現在兩個數字的類型都是 UInt16,可以進行相加。目标常量 twoThousandAndOne 的類型 被推測為 UInt16,因為它是兩個 UInt16 值的和。

SomeType(ofInitialValue)是調用 Swift 構造器并傳入一個初始值的預設方法。在語言内 部,UInt16 有一個構造器,可以接受一個 UInt8 類型的值,是以這個構造器可以用現有的UInt8 來建立一個新的 UInt16。注意,你并不能傳入任意類型的值,隻能傳入 UInt16 内部有對應構造器的值。

2. 整數和浮點數轉換

整數和浮點數的轉換必須顯式指定類型:

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi1 = Double(three) + pointOneFourOneFiveNine
// pi 等于 3.14159,是以被推測為 Double 類型           

複制

這個例子中,常量 three 的值被用來建立一個 Double 類型的值,是以加号兩邊的數類型相 同。如果不進行轉換,兩者無法相加。

浮點數到整數的反向轉換同樣行,整數類型可以用 Double 或者 Float 類型來初始化:

// integerPi 等于 3,是以被推測為 Int 類型
let integerPi = Int(pi1)           

複制

當用這種方式來初始化一個新的整數值時,浮點值會被截斷。也就是說 4.75 會變成 4,-3.9 會變成-3。

注意:結合數字類常量和變量不同于結合數字類字面量。字面量 3 可以直接和字面量0.14159 相加,因為數字字面量本身沒有明确的類型。它們的類型隻在編譯器需要求值的 時候被推測。

三:類型别名

類型别名(type aliases)就是給現有類型定義另一個名字。你可以使用 typealias 關鍵字來定 義類型别名。

當你想要給現有類型起一個更有意義的名字時,類型别名非常有用。假設你正在處理特定長度的外部資源的資料:

typealias AudioSample = UInt16           

複制

定義了一個類型别名之後,你可以在任何使用原始名的地方使用别名:

// maxAmplitudeFound 現在是 0
var maxAmplitudeFound = AudioSample.min           

複制

本例中,AudioSample 被定義為 UInt16 的一個别名。因為它是别名,AudioSample.min實際上是 UInt16.min,是以會給 maxAmplitudeFound 賦一個初值 0。