Enumerations and Structures
github:Swift基礎(chǔ)實(shí)例
github:SwiftBasicTableView
枚舉
- 枚舉
用enum
創(chuàng)建一個(gè)枚舉,與類和所有其他指定的類型一樣,枚舉可以擁有和它相關(guān)聯(lián)的方法:
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
}
讓它包含一個(gè)和它關(guān)聯(lián)的方法 simpleDescription()
:
enum Rank: Int {
//enum case must declare a raw value when the preceding raw value is not an integer
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
func simpleDescription() ->String {
switch self {
case .Ace:
return "ace"
case .Jack:
return "jack"
case .Queen:
return "queen"
case .King:
return "king"
default:
return String(self.rawValue)
}
}
}
let ace = Rank.Ace
let aceRawValue = ace.rawValue //1
let aceString = ace.simpleDescription() //"ace"
- 上面代碼中
case Ace = 1
淫僻,1
是Ace
的原始值躯嫉,稱為rawValue
,類型是Int
稳诚,后面的枚舉值依次遞增哗脖,如Two
就是2
,依次類推扳还。 - 枚舉的類型也可以
String
或Float
類型才避,但是除了Int
類型之外,其他類型的rawValue
都不可以遞增氨距,每一個(gè)enum case
都需要指定一個(gè)相應(yīng)類型的值作為它的rawValue
桑逝。
- 枚舉構(gòu)造器
帶有rawValue
的enum
會(huì)自動(dòng)接收一個(gè)可失敗構(gòu)造器init?(rawValue:)
,它根據(jù)枚舉其中一個(gè)raw value
俏让,找到合適的case
楞遏,生成枚舉的實(shí)例對(duì)象;如果沒(méi)有匹配到合適的case
首昔,則返回nil
:
let convertRank = Rank(rawValue: 3)
if convertRank != nil {
let threeDescription = convertRank.simpleDescription()
print(threeDescription) //"3"
}
else {
print("Have no this enum")
}
- 可失敗構(gòu)造器請(qǐng)參考 概念解釋
- 枚舉的值
在枚舉中case
后的值就是枚舉實(shí)際的值寡喝,不僅僅是它們的raw value
的另一種寫(xiě)法。實(shí)際上勒奇,也可以不為枚舉提供raw value
:
enum Suit {
case Spades, Hearts, Diamonds, Clubs
func simpleDescription() ->String {
switch self {
case .Spades:
return "spades"
case .Hearts:
return "hearts"
case .Diamonds:
return "diamonds"
case .Clubs:
return "clubs"
}
}
}
let hearts = Suit.Hearts
// 在這個(gè)枚舉中预鬓,我們沒(méi)有提供 `raw value` ,當(dāng)強(qiáng)行調(diào)用 rawValue 時(shí),編譯器會(huì)把 `rawValue` 當(dāng)做一個(gè)成員變量赊颠,因此會(huì)報(bào)錯(cuò):找不到這個(gè)成員
// let rawValue = hearts.rawValue;
let heartsDes = hearts.simpleDescription() //"hearts"
注意上面 Hearts
有兩種被引用方式格二,第一種是在 switch
中,通過(guò)簡(jiǎn)寫(xiě)形式 .Hearts
; 第二種是通過(guò) Suit.Hearts
巨税,給 hearts
賦值蟋定。第一種是因?yàn)橥ㄟ^(guò) self
已經(jīng)知道是 Suit
,所以可以使用簡(jiǎn)寫(xiě)形式.Hearts
草添;第二種由于 hearts
沒(méi)有明確給出類型驶兜,所以只能寫(xiě)全名。因此远寸,以下的寫(xiě)法也是對(duì)的:
switch self { case Suit.Hearts:......}
let heartAbb: Suit = .Hearts
- 枚舉的關(guān)聯(lián)值(
associated values
)
枚舉的case
值可以存儲(chǔ)一些和它相關(guān)的其他類型的值抄淑,稱為關(guān)聯(lián)值(associated values
)。
比如一個(gè)商品的條形碼驰后,條形碼由4部分0-9的數(shù)字組成:第一部分是只有1個(gè)數(shù)字的數(shù)字位
;第二部分是5個(gè)數(shù)字的制造位
肆资;第三部分是5個(gè)數(shù)字的產(chǎn)品位
;第四部分是1個(gè)數(shù)字的校驗(yàn)位
灶芝。一個(gè)二維碼卻可以包含所有一維碼的信息郑原,同時(shí)還可以包含一些其他信息唉韭。我們用枚舉的形式來(lái)表現(xiàn)這個(gè)二維碼:
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
上面代碼可以理解為:一個(gè)枚舉名字叫 Barcode
,這個(gè)枚舉包含一個(gè)值 UPCA
犯犁,UPCA
有一個(gè)類型為(Int, Int, Int, Int)
的關(guān)聯(lián)值属愤,或者包含一個(gè)值 QRCode
,QRCode
有一個(gè)類型為(String)
的關(guān)聯(lián)值。生成一個(gè)含有關(guān)聯(lián)值的枚舉對(duì)象:
var barcode = Barcode.UPCA(9, 72345, 77787, 8)
//barcode 被替換為QRCode(String),barcode 只能存儲(chǔ)其中之一
barcode = .QRCode("abcdef")
switch barcode {
case .UPCA(let numberSystem, let manufacture, let product, let check):
print("UPC-A: \(numberSystem) \(manufacture) \(product) \(check)")
case .QRCode(let productCode):
print("QR Code: \(productCode)")
}
//prints "QR Code: abcdef"
如果關(guān)聯(lián)值的類型都是常量(constant)
或變量(variable)
酸役,那么只需要在 case
前寫(xiě)一個(gè) let
或 var
住诸,就可以了:
switch barcode {
case let .UPCA(numberSystem, manufacture, product, check):
print("UPC-A: \(numberSystem) \(manufacture) \(product) \(check)")
case let .QRCode(productCode):
print("QR Code: \(productCode)")
}
//prints "QR Code: abcdef"
結(jié)構(gòu)體
- 用關(guān)鍵字
struct
創(chuàng)建一個(gè)結(jié)構(gòu)體。
結(jié)構(gòu)體(struct
) 和 類(class
)有很多相似的地方涣澡,也包含有屬性贱呐、方法和初始化構(gòu)造器。主要來(lái)看一下它們的不同點(diǎn): -
class
有繼承入桂,struct
沒(méi)有 - 在
runtime
期間奄薇,根據(jù)Type casting
(類型轉(zhuǎn)換),可以得知一個(gè)實(shí)例(instance
)所屬于的類 -
class
有析構(gòu)函數(shù)事格,struct
沒(méi)有 -
class
可以使用 ARC
最重要的惕艳,結(jié)構(gòu)體屬于值類型,在代碼中傳遞的時(shí)候驹愚,每次都會(huì)被復(fù)制(copy
)一份远搪,而類是通過(guò)引用(reference
)傳遞的:
struct Card {
var score : Int
}
let cart = Cart(score: 3)
var varCart = cart
varCart.score = 5
print(cart.score) // 3
print(varCart.score) // 5
可以看到,我們把對(duì)象 cart
賦值給 varCart
后逢捺,修改 varCart
的屬性值谁鳍,并不會(huì)對(duì) cart
的屬性值造成影響。這和下面的 class
完全不同:
class testInit {
var number = 0
var point = 9
}
let testI = testInit()
let testII = testI
testII.point = 8
print(testI.point) // 8
當(dāng)我們把對(duì)象 testI
賦值給 testII
后劫瞳,修改 testII
的屬性 point
倘潜,由于類是引用類型(相應(yīng)說(shuō)明參考概念解釋),
通過(guò)下面的代碼志于,我們來(lái)認(rèn)識(shí) struct
中很重要的一個(gè)概念:成員構(gòu)造器涮因。(該構(gòu)造器的說(shuō)明請(qǐng)參考 概念解釋)
struct Card {
var rank : Rank
var suit : Suit
func simpleDescription()-> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeDes = threeOfSpades.simpleDescription() //"The 3 of spades"
上面的代碼中,我們使用了函數(shù) Card(_: , _: )
生成一個(gè)對(duì)象伺绽,此函數(shù)是 struct
自動(dòng)接收的养泡,稱為 成員構(gòu)造器 (Memberwise initializer)
。
需要注意到是奈应,上面結(jié)構(gòu)體內(nèi)的兩個(gè)屬性 rank
和 suit
在聲明時(shí)并沒(méi)有初始化澜掩,而是在生成 threeOfSpades
實(shí)例對(duì)象的時(shí)候才初始化,因此杖挣,結(jié)構(gòu)體只接收一個(gè)成員構(gòu)造器肩榕。如果這兩個(gè)屬性在聲明的時(shí)候都已經(jīng)初始化,那么惩妇,結(jié)構(gòu)體將接收兩個(gè)構(gòu)造器:Card()
和 Card(_: , _: )
株汉。少初始化任何一個(gè)屬性筐乳,都只會(huì)接收一個(gè)構(gòu)造器:Card(_: , _: )
。