Enumerations and Structures
github:Swift基础实例
github:SwiftBasicTableView
枚举
- 枚举
用enum
创建一个枚举,与类和所有其他指定的类型一样,枚举可以拥有和它相关联的方法:
enum Rank: Int {
case Ace = 1
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
case Jack, Queen, King
}
让它包含一个和它关联的方法 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
都不可以递增,每一个enum case
都需要指定一个相应类型的值作为它的rawValue
。
- 枚举构造器
带有rawValue
的enum
会自动接收一个可失败构造器init?(rawValue:)
,它根据枚举其中一个raw value
,找到合适的case
,生成枚举的实例对象;如果没有匹配到合适的case
,则返回nil
:
let convertRank = Rank(rawValue: 3)
if convertRank != nil {
let threeDescription = convertRank.simpleDescription()
print(threeDescription) //"3"
}
else {
print("Have no this enum")
}
- 可失败构造器请参考 概念解释
- 枚举的值
在枚举中case
后的值就是枚举实际的值,不仅仅是它们的raw value
的另一种写法。实际上,也可以不为枚举提供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
// 在这个枚举中,我们没有提供 `raw value` ,当强行调用 rawValue 时,编译器会把 `rawValue` 当做一个成员变量,因此会报错:找不到这个成员
// let rawValue = hearts.rawValue;
let heartsDes = hearts.simpleDescription() //"hearts"
注意上面 Hearts
有两种被引用方式,第一种是在 switch
中,通过简写形式 .Hearts
; 第二种是通过 Suit.Hearts
,给 hearts
赋值。第一种是因为通过 self
已经知道是 Suit
,所以可以使用简写形式.Hearts
;第二种由于 hearts
没有明确给出类型,所以只能写全名。因此,以下的写法也是对的:
switch self { case Suit.Hearts:......}
let heartAbb: Suit = .Hearts
- 枚举的关联值(
associated values
)
枚举的case
值可以存储一些和它相关的其他类型的值,称为关联值(associated values
)。
比如一个商品的条形码,条形码由4部分0-9的数字组成:第一部分是只有1个数字的数字位
;第二部分是5个数字的制造位
;第三部分是5个数字的产品位
;第四部分是1个数字的校验位
。一个二维码却可以包含所有一维码的信息,同时还可以包含一些其他信息。我们用枚举的形式来表现这个二维码:
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
上面代码可以理解为:一个枚举名字叫 Barcode
,这个枚举包含一个值 UPCA
,UPCA
有一个类型为(Int, Int, Int, Int)
的关联值,或者包含一个值 QRCode
,QRCode
有一个类型为(String)
的关联值。生成一个含有关联值的枚举对象:
var barcode = Barcode.UPCA(9, 72345, 77787, 8)
//barcode 被替换为QRCode(String),barcode 只能存储其中之一
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"
如果关联值的类型都是常量(constant)
或变量(variable)
,那么只需要在 case
前写一个 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"
结构体
- 用关键字
struct
创建一个结构体。
结构体(struct
) 和 类(class
)有很多相似的地方,也包含有属性、方法和初始化构造器。主要来看一下它们的不同点: -
class
有继承,struct
没有 - 在
runtime
期间,根据Type casting
(类型转换),可以得知一个实例(instance
)所属于的类 -
class
有析构函数,struct
没有 -
class
可以使用 ARC
最重要的,结构体属于值类型,在代码中传递的时候,每次都会被复制(copy
)一份,而类是通过引用(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
可以看到,我们把对象 cart
赋值给 varCart
后,修改 varCart
的属性值,并不会对 cart
的属性值造成影响。这和下面的 class
完全不同:
class testInit {
var number = 0
var point = 9
}
let testI = testInit()
let testII = testI
testII.point = 8
print(testI.point) // 8
当我们把对象 testI
赋值给 testII
后,修改 testII
的属性 point
,由于类是引用类型(相应说明参考概念解释),
通过下面的代码,我们来认识 struct
中很重要的一个概念:成员构造器。(该构造器的说明请参考 概念解释)
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"
上面的代码中,我们使用了函数 Card(_: , _: )
生成一个对象,此函数是 struct
自动接收的,称为 成员构造器 (Memberwise initializer)
。
需要注意到是,上面结构体内的两个属性 rank
和 suit
在声明时并没有初始化,而是在生成 threeOfSpades
实例对象的时候才初始化,因此,结构体只接收一个成员构造器。如果这两个属性在声明的时候都已经初始化,那么,结构体将接收两个构造器:Card()
和 Card(_: , _: )
。少初始化任何一个属性,都只会接收一个构造器:Card(_: , _: )
。