iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0

基本型別 ( Swift Basic Types )

帶你一起來看不能不知道的 Swift 基本型別


整數 ( Intergers )

整數是沒有小數點的數值,可分為:

  • 有符號 → 正數、負數或是零
  • 無符號 → 正數或零

Swift 提供了 8、16、32 以及 64 位元的整數型別,命名規則跟 C 很相似。

  • 8 位元的無符號整數叫做 UInt8
  • 64 位元的有符號整數叫做 Int64

整數的範圍 ( Integer Bounds )

無符號整數來說,可以從官方的 Intergers API Swift > Math > Intergers 來看,有一個 UnsignedInteger 的協定,並且在下方擴展了 UnsignedInteger ,在裡面宣告兩個靜態變數 max 和 min,這樣一來可以藉由這兩個屬性來取得最大值以及最小值。

public protocol UnsignedInteger : BinaryInteger {
}

extension UnsignedInteger where Self : FixedWidthInteger {
	// ... 略 ...
	
	/// The maximum representable integer in this type.
    ///
    /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where
    /// `**` is exponentiation.
    public static var max: Self { get }

    /// The minimum representable integer in this type.
    ///
    /// For unsigned integer types, this value is always `0`.
    public static var min: Self { get }
}

所以我們就可以這樣來取得 UInt8 最大和最小值。

let maximumValue = UInt8.max
let minimumValue = UInt8.min

有符號整數也是一樣的喔 /images/emoticon/emoticon07.gif

同一份檔案中,可以看到有個叫做 SignedInteger 的協定,在擴展協定中也有兩個靜態變數:maxmin

public protocol SignedInteger : BinaryInteger, SignedNumeric {
}

extension SignedInteger where Self : FixedWidthInteger {
	// ... 略 ...
		
	/// The maximum representable integer in this type.
    ///
    /// For signed integer types, this value is `(2 ** (bitWidth - 1)) - 1`,
    /// where `**` is exponentiation.
    public static var max: Self { get }

    /// The minimum representable integer in this type.
    ///
    /// For signed integer types, this value is `-(2 ** (bitWidth - 1))`, where
    /// `**` is exponentiation.
    public static var min: Self { get }
}

Int 與 UInt

一般來說,在定義一個整數時,我們不太會去特別定義要使用多少位元的整數,通常都會直接使用 Int 或是 UInt,Swift 也提供了這兩種特別的整數型別,然而這個型別使用的位元長度就等於你電腦使用的位元長度。

  • 在 32-bit 的環境,Int 等同於 Int32
  • 在 64-bit 的環境,Int 等同於 Int64

然而無符號整數也是這樣。

浮點數 ( Float, Double )

浮點數是帶有小數點的數值,分為兩種類型:

  • 單精度浮點數 ( Float ) → 佔用記憶體 32bits
  • 雙精度浮點數 ( Double ) → 佔用記憶體 64bits

顧名思義,兩個的差異就差在精確度, Float 可表示 6 位數,但是 Double 至少可以表示 15 位數。

還記得上一篇提到的型別推斷嗎?在宣告浮點數時,如果不特別標記型別的話,會自動推斷為 Double 型別。

let bmi = 23.79 // Type is Double.
let bmi: Float = 23.79 // Type is Float.

let pi = 3 + 0.14159 // Type is Double.

至於如何選擇,就要看你的需求,如果數值在哪種型態都適用的情況下,還是會建議用 Double,至少能避免溢位造成的錯誤。

數值的型別轉換 ( Numeric Type Conversion )

溢位問題 ( Overflow )

即使我們知道要宣告的變數或是常數是非負數時,我們也不會特別去註記 UInt;或是已經知道數值的範圍大概會落在什麼區間,也不太會去特別宣告要使用什麼大小的整數型別,這樣一來就可以直接使用,不用擔心任何意外錯誤。

除非今天要做到優化或是特別處理時,才會特別定義其他整數型別,這也有個好處是可以快速知道溢位的問題,官方文件上有提到一個例子:

let cannotBeNegative: UInt8 = -1
// UInt8 不可為負數值
let tooBig: Int8 = Int8.max + 1
// Int8 的最大值 + 1 會造成溢位錯誤

轉換 ( Conversion )

如果今天要將兩個不同型別的變數或常數互相做運算,此時就需要轉換成相同型別,以下面這個例子為例:

let three = 3
let decimal = 0.14159
let pi = Double(three) + decimal

如果沒有將 three 轉換成 Double 型別的話,在編譯時會跳出 Binary operator '+' cannot be applied to operands of type 'Int' and 'Double,不允許這樣執行加法。

但是在浮點數那個段落裡,為什麼可以不用轉換型別就可以將 3 跟 0.14159 相加?

monkey shock

如果是數字直接做運算,在 runtime 的時候才會去針對運算結果的值做 Type Inference,但是如果已經先透過變數或常數來儲存數值,並且利用他們來做運算,在 Compile Time 就會發現型別不相符,所以就要先透過型別轉換才能執行運算

型別別名 ( Type Aliases )

簡單來說就是將型別取一個綽號,可以透過 typealias 這個關鍵字來實作。

當你想透過上下文,替既有的型別給予一個更清楚的別名時,這個方式就很好用。

typealias SampleRateConversion = UInt16
let maximumValue = SampleRateConversion.max

SampleRateConversion 定義為 UInt16 的別名,實際上 SampleRateConversion.max 會去呼叫 UInt16.max,再回傳給 maximumValue 常數。

布林值 ( Booleans )

Swift 的布林型別叫做 Bool,布林值又稱邏輯值,因為他只能是 true 或是 false

let 我的身高有一百八 = true
let 太陽從西邊升起 = false

跟上面的 Double 以及 Int 一樣,透過型別推論初始值可以得知,這兩個常數的型別都是 Bool,透過型別推論,也可以讓程式碼更簡潔有力,對於流程控制布林值就很方便,之後章節會再提到。

if 我身高有一百八 {
	print("人生勝利了")
} else {
	print("人小志氣高")
}

// 最後會 print 出 "人生勝利了"

元組 ( Tuples )

你可以使用 Tuple 將多個資料( 可以不同型別 )組合成一個複合值,可以用來存取及傳遞。

舉個例子,這邊有一個 Tuple 用來存取公車編號以及路徑名稱。

let ilanBus = (1879, "羅東-圓山")
// ilanBus 是一個 (Int, String) 的 Tuple。

在宣告變數你也可以使用 Tuple 作為初始值。

let (busNumber, busRoute) = ilanBus
print("The bus number is \(busNumber)")
print("The bus route is \(busRoute)")

如果你只需要 Tuple 中某些資料時,你可以使用 _ 忽略。

let (busNumber, _) = ilanBus
print("The bus number is \(busNumber)")

如果你不想透過變數或常數來去存取資料的話,你也可以在 Tuple 後面加索引值 ( 第一個索引值為 0 ) 去取得裡面的資料。

print("The bus number is \(ilanBus.0)")
// Prints "The bus number is 1879"
print("The bus route is \(ilanBus.1)")
// Prints "The bus route is 羅東-圓山"

但是用這種索引值的方式,就程式碼的易讀性來說會比較差,所以你可以替每個值命名,這樣程式碼看起來就比較清楚在做什麼。

let ilanBus = (busNumber: 1879, busRoute: "羅東-圓山")
print("The bus number is \(ilanBus.busNumber)")
print("The bus route is \(ilanBus.busRoute)")

以上就是 Swift 的基本型別,但你一定想說很奇怪...
難道 Swift 的基本型別中沒有字串嗎? /images/emoticon/emoticon70.gif

答案是有的,下回就來談談 Strings and Characters。


上一篇
Day 2 | Swift 起源、基礎特性
下一篇
Day 4 | Swift 字串和字元
系列文
給我 30 天,給你一輩子:Swift 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言