Swift进阶杂谈6:枚举

C语言枚举的写法回顾

在了解Swift的枚举以前,咱们回顾下C语言的枚举写法:swift

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默认枚举值是整型markdown

<!--一、写法一-->
enum Weak{
    case MON
    case TUE
    case WED
    case THU
    case FRI
    case SAT
    case SUN
}

<!--二、写法二-->
//也能够直接一个case,而后使用逗号隔开
enum Weak{
    case MON, TUE, WED, THU, FRI, SAT, SUN
}

<!--定义一个枚举变量-->
var w: Weak = .MON
复制代码

上诉代码中咱们的枚举类型默认是整型,这个和C是一致的,若是咱们想要表达的String怎么办?能够经过指定enum的枚举值的类型来建立,其中枚举值和原始值rawValue的关系为case 枚举值 = rawValue原始值app

/*
 =左边的值是枚举值,例如 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。spa

若是只是对于Int类型适用,对于String类型也是同样适用的。 接下来咱们要区分一个东西,咱们看如下代码的打印结果3d

enum DayOfWeek:String {
    case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
print(DayOfWeek.monday) //这里输出的是什么
复制代码

经过运行得知,这里输出为monday。这里须要注意的一点就是枚举值RawValue是两个不一样的东西,好比咱们没有办法把一个枚举值分配一个String的变量,即便这个enumString类型。 与此同时,咱们也没办法把一个具体类型的数据分配给具体的枚举类型,好比以下例子报错 因此上面print出来的就是具体的枚举值,而经过rawValue访问的就是rawValueget方法code

  • 若是enum没有声明类型,是没有rawValue属性的

枚举的遍历

那咱们的枚举是否是能够像集合那样遍历?答案是能够的orm

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来表达更复杂的例子,关联更多的信息。这个时候咱们须要使用到关联值了。 好比咱们经过枚举值来表达一个形状,有圆形,长方形,正方形。圆形有半径,长方形有宽,高,这个时候关联值就显得很是有用了ci

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
复制代码

总结

  • 一、enum中使用rawValue的本质是调用get方法,即在get方法中从Mach-O对应地址中取出字符串并返回的操做
  • 二、enum中init方法的调用是经过枚举.init(rawValue:)或者枚举(rawValue:)触发的
  • 三、没有关联值的enum,若是但愿获取全部枚举值,须要遵循CaseIterable协议,而后经过枚举名.allCase的方式获取
  • 四、case枚举值和rawValue原始值的关系:case 枚举值 = rawValue原始值
  • 五、具备关联值的枚举,能够成为三无enum,由于没有别名RawValue、init、计算属性rawValue
  • 六、enum的模式匹配方式,主要有两种:switch / if case
  • 七、enum能够嵌套enum,也能够在结构体中嵌套enum,表示该enum是struct私有的
  • 八、enum中还能够包含计算属性、类型属性,可是不能包含存储属性
  • 九、enum中能够定义实例 + static修饰的方法
相关文章
相关标签/搜索