枚举enum
本小节讨论的枚举是一种基础类型,并不是对象。在Swift中,枚举有很多高级特性。
语法结构
enum EnumName : Type { case... }
,其中Type可以省略,{}中定义的枚举体至少包含一个case语句。
一个简单的实现如下,在名为TextAlignment的枚举中定义了4个可选的值:
enum TextAlignment {
case left
case right
case center
case justify
}
常用操作
一般就是取值和轮询这两种操作用的比较多。
enum TextAlignment {
case left
case right
case center
case justify
}
//获取
var alignment = TextAlignment.justify
var alignment:TextAlignment = TextAlignment.justify
//比较
if (alignment == TextAlignment.justify){
}
//用于switch,这个例子中的.left是一种简写模式,并不建议这样来写代码。
var alignment = TextAlignment.justify //justify
switch alignment {
case .left:
print("left aligned")
case .right:
print("right aligned")
case .center:
print("center aligned")
case .justify:
print("justified")
}
关于:特殊写法就是点”.“,这是一种简写方法,前提是在先有第一行代码完整调用一次枚举后,才能简写(这是编译器一个自动推断数据类型功能)
//如果没这行代码,则程序会报错,但实际代码编写过程中不建议这样来写
var alignment = TextAlignment.justify
alignment = .right
设置原始值
下面是一些细节的处理,比始原始值设置,反向查询等。
// 设置原始化,如果不设置 = 后面的原始值的话,swift会对int类型的枚举从0开始设置值,然后按元素个数依次累加
enum TextAlignment : Int {
case left = 20
case right = 30
case center = 40
case justify = 50
}
//这种定义方式的话,其值默认和名称是相同的,但只局限于字符枚举
/**
enum ProgrammingLanguage : String {
case swift
case objectiveC = "objective-c"
case c
case cpp = "c++"
case java
}
*/
//取值-名, ~~ justify
var alignment = TextAlignment.justify
var alignment:TextAlignment = TextAlignment.justify
//取值-值 : ~~ Left has raw value 20
print("Left has raw value \(TextAlignment.left.rawValue)")
//反向查询, ~~ left
var t = TextAlignment(rawValue: 20)
在枚举中定义函数
swift的枚举可以关联方法。
//创建一个新枚举
enum LightBulb {
case on
case off
//添加一个函数
func surfaceTemperature(forAmbientTemperature ambient: Double) -> Double {
switch self { //self是一个隐式参数,类型是LightBulb
case .on:
return ambient + 150.0
case .off:
return ambient
}
}
mutating func toggle() { //注意这个关键字的使用,否则无法更改枚举的值
switch self {
case .on:
self = .off
case .off:
self = .on
}
}
}
var bulb = LightBulb.on
let ambientTemperature = 77.0
var bulbTemperature = bulb.surfaceTemperature(forAmbientTemperature: ambientTemperature)
//the bulb's temperature is 227.0
print("the bulb's temperature is \(bulbTemperature)")
bulb.toggle() //off,相当于返回了一个值给bulb变量重新赋值
bulbTemperature = bulb.surfaceTemperature(forAmbientTemperature: ambientTemperature)
//the bulb's temperature is 77.0
print("the bulb's temperature is \(bulbTemperature)")
mutating关键字,在swift中枚举是值类型,而值类型的方法不能对self进行修改,如果想修改需要声明 mutaing 关键字
给枚举元素设置不同的值
这个功能可以把数据附在枚举实例上,不同的成员可以有不同类型的关联值。
enum ShapeDimensions {
// 点没有关联值
case point
// 正方形的关联值是边长,类型是(元组)
case square(side: Double)
// 长方形的关联值是宽和高,类型是(元组)
case rectangle(width: Double, height: Double)
//面积计算
func area() -> Double {
switch self {
case .point:
return 0
case let .square(side: side):
print("hi")
return side * side
case let .rectangle(width: w, height: h):
return w * h
}
}
}
//square(side: 10.0),创建了一个边长是10的正方形
var squareShape = ShapeDimensions.square(side: 10.0)
//rectangle(width: 5.0, height: 10.0),创建了宽和高为5*10的长方形
var rectShape = ShapeDimensions.rectangle(width: 5.0, height: 10.0)
//~~ square's area = 100.0
print("square's area = \(squareShape.area())")
//~~ rectangle's area = 50.0
print("rectangle's area = \(rectShape.area())")
//~~ point's area = 0.0
var pointShape = ShapeDimensions.point
print("point's area = \(pointShape.area())")
用枚举实现递归
构建如下图所示的族谱
indirect
关键字是为了递归数据内存占用不确定而增设的。fatherAncestors是祖先的意思
enum FamilyTree {
case noKnownParents
indirect case oneKnownParent(name: String, ancestors: FamilyTree)
indirect case twoKnownParents(fatherName: String, fatherAncestors: FamilyTree,
motherName: String, motherAncestors: FamilyTree)
}
//~~ twoKnownParents(fatherName: "Fred Sr.", fatherAncestors:
let fredAncestors = FamilyTree.twoKnownParents(
fatherName: "Fred Sr.",
fatherAncestors: .oneKnownParent(name: "Matilta",
ancestors: .noKnownParents),
motherName: "Marsha",
motherAncestors: .noKnownParents)
indirect 关键字,用来告诉编译器把枚举的数据放到一个指针指向的地方,防止内存溢出。
本质来说,这东西是用来代替Objective-C的头文件的。
结构体
结构体(struct)是把相关数据块组合在一起放在内存中的一种类型。当需要把数据组合为一种通用类型时就可以用结构体。
语法结构:
struct structName { }
,可定义属性也可以定义方法,可简单理解为类的简化版本
简单示例
//Town.swift
struct Town { //定义了一个名为Town的结构体
//定义了两个属性
var population = 5422
var numberOfStoplights = 4
//定义实例方法
func printDescription() {
print("Population: \(population); number of stop lights: \(numberOfStoplights)")
}
//修改方法,需要添加mutating关键字
mutating func changePopulation(by amount: Int) {
population += amount
}
}
测试代码
//main.swift
import Foundation
var myTown = Town();
print(myTown.population) //5422
myTown.printDescription() //Population: 5422; number of stop lights: 4
myTown.changePopulation(by: 500)
print(myTown.population) //5922
也可以在结构体中定义类型方法
struct Town {
static func numberOfSides() -> Int {
return 4
}
} //Town.numberOfSides()
结构体中定义静态方法
上面例子中如果在结构体中定义了方法都需要先实例化结构体,再进行方法调用,如果用static进行声明后就不需要实例化枚举了。如下:
struct Square {
static func number() -> Int{
return 4
}
}
let v = Square.number()