C语言枚举的写法回顾
在了解Swift的枚举之前,我们回顾下C语言的枚举写法:
enum 枚举名 {
枚举值1,
枚举值2,
....
};
<!--举例:表示一周7天-->
enum Weak{
MON, TUE, WED, THU, FRI, SAT, SUN
};
<!--更改C中枚举默认值-->
//如果没有设置枚举默认值,一般第一个枚举成员的默认值为整型0,后面依次递推,如果我们想更改,只需要这样操作
enum Weak{
MON = 1, TUE, WED, THU, FRI, SAT, SUN
};
<!--C中定义一个枚举变量-->
//表明创建了一个枚举,并声明了一个枚举变量weak
enum Weak{
MON = 1, TUE, WED, THU, FRI, SAT, SUN
}weak;
//或者下面这种写法,省略枚举名称
enum{
MON = 1, TUE, WED, THU, FRI, SAT, SUN
}weak;
Swift中的枚举写法类比
在swift中,枚举的创建方式如下,如果没有指定枚举值的类型,那么enum默认枚举值是整型的
<!--1、写法一-->
enum Weak{
case MON
case TUE
case WED
case THU
case FRI
case SAT
case SUN
}
<!--2、写法二-->
//也可以直接一个case,然后使用逗号隔开
enum Weak{
case MON, TUE, WED, THU, FRI, SAT, SUN
}
<!--定义一个枚举变量-->
var w: Weak = .MON
上诉代码中我们的枚举类型默认是整型,这个和C是一致的,如果我们想要表达的String怎么办?可以通过指定enum的枚举值的类型来创建,其中枚举值和原始值rawValue的关系为case 枚举值 = rawValue原始值
/*
=左边的值是枚举值,例如 MON
=右边的值在swift中称为 RawValue(原始值),例如 "MON"
两者的关系为:case 枚举值 = rawValue原始值
*/
enum Weak: String{
case MON = "MON"
case TUE = "TUE"
case WED = "WED"
case THU = "THU"
case FRI = "FRI"
case SAT = "SAT"
case SUN = "SUN"
}
- 如果不想写枚举值后的字符串,也可以使用
隐式RawValue分配,隐式RawValue分配是建立在Swift的类型推断机制上的,如下我们先用Int来举例说明:
<!--Int类型-->
//MON是从0开始一次递推,而WED往后是从10开始一次递推
enum ShortDayWeak: Int{
case mon, tue, wed, thu, fri = 10, sat, sun
}
系统默认是从0开始,在这个过程中你可以指定fri = 10,那么对于sat,系统会从根据前一个case的值来做累加的操作,也就是11。
如果只是对于Int类型适用,对于String类型也是一样适用的。
接下来我们要区分一个东西,我们看以下代码的打印结果
enum DayOfWeek:String {
case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
print(DayOfWeek.monday) //这里输出的是什么
通过运行得知,这里输出为monday。这里需要注意的一点就是枚举值和RawValue是两个不同的东西,比如我们没有办法把一个枚举值分配一个String的变量,即使这个enum是String类型。
与此同时,我们也没办法把一个具体类型的数据分配给具体的枚举类型,比如如下例子报错
所以上面
print出来的就是具体的枚举值,而通过rawValue访问的就是rawValue的get方法。
- 如果enum没有声明类型,是没有rawValue属性的
枚举的遍历
那我们的枚举是不是可以像集合那样遍历?答案是可以的
enum week:String {
case mon, tue, wed, thu, fri = "Hello", sat, sun
}
extension week:CaseIterable{}
var allCase = week.allCases
for c in allCase {
print(c)
}
打印如下
关联值 Associated Value Enumerations
上面可以看到隐式分配会给每一个Case分配一个隐式值,但是有时候我们并不想这么做,或者有时候我们想通过enum来表达更复杂的例子,关联更多的信息。这个时候我们需要使用到关联值了。
比如我们通过枚举值来表达一个形状,有圆形,长方形,正方形。圆形有半径,长方形有宽,高,这个时候关联值就显得非常有用了
enum Shape {
case circle(radius: Double)
case rectangle(width: Int, height: Int)
}
注意⚠️这里我们使用了关联值之后,就没有RawValue。这里也非常好理解,因为当前一个case都可以有一组值来表示。
当然这里的radius、height、width是我们取的标签,如果你不想写,那就变成下面这样:
enum Shape {
case circle(Double)
case rectangle(Int, Int)
}
可以通过以下方法创建一个有关联值的枚举值
enum Shape {
case circle(radius: Double)
case rectangle(width: Int, height: Int)
}
//******使用的时候也非常简单,这里就可以直接给定值来创建一个关联的枚举值
var circle = Shape.circle(radius: 10.0)
var rectangle = Shape.rectangle(width: 10, height: 10)
//******也可以重新分配值
circle = Shape.rectangle(width: 10, height: 10)
枚举的其他用法
模式匹配
enum Week:String {
case MONDAY
case TUEDAY
case WEDDAY
case THUDAY
case FRIDAY
case SATDAY
case SUNDAY
}
let currentWeek:Week = .FRIDAY
switch currentWeek{
case .MONDAY: print(Week.MONDAY.rawValue)
case .TUEDAY: print(Week.TUEDAY.rawValue)
case .WEDDAY: print(Week.WEDDAY.rawValue)
case .THUDAY: print(Week.THUDAY.rawValue)
case .FRIDAY: print(Week.FRIDAY.rawValue)
case .SATDAY: print(Week.SATDAY.rawValue)
case .SUNDAY: print(Week.SUNDAY.rawValue)
}
使用Switch匹配enum的时候我们必须列举当前所有的情况,不然编译器就会报错:
如果不想匹配这么多的case,那么我们就可以使用default关键字来代表默认的情况
enum Week:String {
case MONDAY
case TUEDAY
case WEDDAY
case THUDAY
case FRIDAY
case SATDAY
case SUNDAY
}
let currentWeek:Week = .FRIDAY
switch currentWeek{
case .SATDAY, .SUNDAY: print("Happy Day")
default : print("Sad Day")
}
如果我们要匹配关联值的话
enum Shape {
case circle(radius: Double)
case rectangle(width: Int, height: Int)
}
let shape = Shape.circle(radius: 10.0)
switch shape{
/*这里我们做了Value-binding,也就意味着如果case匹配上,我们相当于把10赋值给常量radious*/
case let .circle(radius):
print("Circle radius:\(radius)")
break
case let .rectangle(width, height):
print("rectangle width:\(width),height\(height)")
break
}
还可以这么写
enum Shape {
case circle(radius: Double)
case rectangle(width: Int, height: Int)
}
let shape = Shape.circle(radius: 10.0)
switch shape{
case .circle(let radius):
print("Circle radius:\(radius)")
break
case .rectangle(let width, var height):
print("rectangle width:\(width),height\(height)")
break
}
有时候在业务逻辑处理中我们只是想匹配单个case,我们可以这样写
var circle = Shape.circle(radius: 10.0)
if case let Shape.circle(radius) = circle {
print("Circle radius:\(radius)")
}
如果我们只关心不同case的相同关联值,我们可以这么写
enum Shape {
case circle(radius: Double, diameter: Double)
case rectangle(width: Double, height: Double)
case square(width: Double, width:Double)
}
let shape = Shape.circle(radius: 10.0, diameter: 20.0)
switch shape {
case let .circle(x, 20.0), let .square(x, 20.0):
print(x)
break
default:
break
}
或者使用通配符的方式:
let shape = Shape.circle(radius: 10.0, diameter: 20.0)
switch shape {
case let .circle(_, x), let .square(x, _):
print(x)
break
default:
break
}
/**/
switch shape{
case let .circle(x, y), let .square(y, x):
print("x = \(x),y = \(y)")
break
default:
break
}
枚举嵌套
比如我们的游戏案例,不同的案件组合会有不同的技能产生
enum CombineDirect{
//基础按键就4个
enum BaseDirect{
case up
case down
case left
case right
}
//带来的组合按键
case leftUp(combineElement1: BaseDirect, combineElement2: BaseDirect)
case rightUp(combineElement1: BaseDirect, combineElement2: BaseDirect)
case leftDown(combineElement1: BaseDirect, combineElement2: BaseDirect)
case rightDown(combineElement1: BaseDirect, combineElement2: BaseDirect)
}
//使用方式
let leftUp = CombineDirect.leftUp(combineElement1: CombineDirect.BaseDirect.left, combineElement2: CombineDirect.BaseDirect.up)
结构体中的嵌套
struct Skill{
enum KeyType{
case up
case down
case left
case right
}
let key: KeyType
func launchSkill(){
switch key {
case .left,.right:
print("left, right")
case .down,.up:
print("up, down")
}
}
}
Enum中包含的属性
enum中能够包含计算属性,类型属性,不能包含存储属性,这里简单了解一下:
Enum中包含方法
我们也可以在enum中定义实例方法,static修饰的方法
enum Week:Int {
case MONDAY
case TUEDAY
case WEDDAY
case THUDAY
case FRIDAY
case SATDAY
case SUNDAY
mutating func nextDay(){
if self == .SUNDAY {
self = Week(rawValue: 1)!
}else{
self = Week(rawValue: self.rawValue + 1)!
}
}
}
var currentWeek:Week = .FRIDAY
print("old current \(currentWeek),rawValue \(currentWeek.rawValue)")
currentWeek.nextDay()
print("new current \(currentWeek),rawValue \(currentWeek.rawValue)")
print("end")
<------**输出结果**---->
old current FRIDAY,rawValue 4
new current SATDAY,rawValue 5
end
总结
- 1、enum中使用rawValue的本质是调用get方法,即在get方法中从Mach-O对应地址中取出字符串并返回的操作
- 2、enum中init方法的调用是通过枚举.init(rawValue:)或者枚举(rawValue:)触发的
- 3、没有关联值的enum,如果希望获取所有枚举值,需要遵循CaseIterable协议,然后通过枚举名.allCase的方式获取
- 4、case枚举值和rawValue原始值的关系:case 枚举值 = rawValue原始值
- 5、具有关联值的枚举,可以成为三无enum,因为没有别名RawValue、init、计算属性rawValue
- 6、enum的模式匹配方式,主要有两种:switch / if case
- 7、enum可以嵌套enum,也可以在结构体中嵌套enum,表示该enum是struct私有的
- 8、enum中还可以包含计算属性、类型属性,但是不能包含存储属性
- 9、enum中可以定义实例 + static修饰的方法