美文网首页swift学习
Swift5.1 - 枚举enum(4)

Swift5.1 - 枚举enum(4)

作者: HChase | 来源:发表于2019-06-25 11:05 被阅读49次

1. 枚举的基本用法

  • 使用 enum 关键词来定义 枚举
enum Score {
    case a, b, c, d
}
// 等价于
enum Score {
    case a
    case b
    case c
    case d
}

var score = Score.a
score = .b
print(score) // b

switch score {
case .a:
    print("优秀")
case .b:
    print("良好")
case .c:
    print("及格")
case .d:
    print("不及格")
}

2. 关联值

  • 有时会将枚举的成员值跟 其他类型 的关联存在一起;
enum Score {
    case point(Int)
    case grade(Character)
}

var score = Score.point(90)
score = .grade("A")

switch score {
case let .point(s):      // 获取关联值
    print("score = \(s)")
case let .grade(g):      // 获取关联值
    print("core = \(g)")
}
enum Date {
    case digit(year: Int, month: Int, day: Int)
    case string(String)
}

var date = Date.digit(year: 2019, month: 6, day: 25)
date = .string("2019-06-25")

switch date {
case .digit(let year,let month, let day):  // 获取关联值
    print("year = \(year) , month = \(month), day = \(day)")
case .string(let dateStr):  // 获取关联值
    print(dateStr)
}
  • 必要的时候,可以将 let 改为 var

  • 关联值实际使用场景;


enum Password {
    case number(Int, Int, Int, Int)
    case gesture(String)
}

var pw = Password.number(2, 4, 6, 8)
pw = .gesture("2468")

switch pw {
//case .number(let n1, let n2, let n3, let n4):
case let .number(n1, n2, n3, n4):  // 或者这样写,两种写法等价
    print("n1 = \(n1), n2 = \(n2), n3 = \(n3), n4 = \(n4)")
case let .gesture(g):
    print("gesture = \(g)")
}
  • 关联值的底层存储原理(类似 共用体):
    1. 1个字节存储成员值;
    2. N个字节存储关联值(N取占用内存最大的关联值),任何一个case的关联值都共用这N个字节;
    3. 所以整形关联值的枚举占用的内存大小为:(1 + n) * 8个字节, n 为最大关联数;
 enum TestEnum {
        case test1(Int, Int, Int)
        case test2(Int, Int)
        case test3(Int)
        case test4(Bool)
        case test5
    }
    
    // 1个字节存储成员值
    // N个字节存储关联值(N取占用内存最大的关联值),任何一个case的关联值都共用这N个字节
    // 共用体
    
    // 小端:高高低低
    // 01 00 00 00 00 00 00 00
    // 02 00 00 00 00 00 00 00
    // 03 00 00 00 00 00 00 00
    // 00
    // 00 00 00 00 00 00 00
    var e = TestEnum.test1(1, 2, 3)
    print(Mems.ptr(ofVal: &e))
    
    // 04 00 00 00 00 00 00 00
    // 05 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 01
    // 00 00 00 00 00 00 00
    e = .test2(4, 5)
    print(Mems.memStr(ofVal: &e))
    
    // 06 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 02
    // 00 00 00 00 00 00 00
    e = .test3(6)
    
    // 01 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 03
    // 00 00 00 00 00 00 00
    e = .test4(true)
    
    // 00 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 00 00 00 00 00 00 00 00
    // 04
    // 00 00 00 00 00 00 00
    e = .test5

3. 原始值 (rawValue)

  • 枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做 原始值(rawValue);
  • 原始值 不占用枚举变量内存;
enum Direction: String {
    case east = "东"
    case west = "西"
    case south = "南"
    case north = "北"
}

var direction = Direction.east
print(direction.rawValue)  // 东
direction = .west
print(direction.rawValue)  // 西

4. 隐式原始值

  • 如果枚举的原始值类型为IntString,swift将会自动设置原始值,如下:
enum Direction: String {
    case east = "east"
    case west = "west"
    case south = "south"
    case north = "north"
}

// 等价于
enum Direction: String {
    case east, west, south, north
}

print(Direction.east.rawValue)  // east
print(Direction.west.rawValue)  // west

5. 递归枚举

  • 使用 indirect 关键词,实现 enum 递归;
indirect enum Calculation {
    case number(Int)
    case sum(Calculation, Calculation)
}

// 也可以这样写
//enum Calculation {
//    case number(Int)
//    indirect case sum(Calculation, Calculation)
//}

let five = Calculation.number(5)
let four = Calculation.number(4)
let sum = Calculation.sum(five, four)

func calculation(_ cal: Calculation) -> Int {
    switch cal {
    case let .number(value):
        return value
    case let .sum(cal1, cal2):
        return calculation(cal1) + calculation(cal2)
    }
}

print("sum = \( calculation(sum) )")  // 9

6. MemoryLayout

  • 可以使用 MemoryLayout 来获取 数据类型 占用内存的大小;
enum Date {
    case digit(year: Int, month: Int, day: Int)
    case other
}

print( MemoryLayout<Date>.size )      // 实际占用的内存大小  25 = 3 * 8 + 1   三个整形(每个占用8个字节) + 1个字节(成员值类型 1个字节)
print( MemoryLayout<Date>.stride )    // 系统分配的内存  32 = 4 * 内存对齐参数
print( MemoryLayout<Date>.alignment ) // 内存对齐参数  8
let date = Date.digit(year: 2019, month: 6, day: 25)
print( MemoryLayout.size(ofValue: date) )      // 25
print( MemoryLayout.stride(ofValue: date) )    // 32
print( MemoryLayout.alignment(ofValue: date) ) // 8
let date = Date.other
print( MemoryLayout.size(ofValue: date) )      // 25
print( MemoryLayout.stride(ofValue: date) )    // 32
print( MemoryLayout.alignment(ofValue: date) ) // 8

源代码demo

相关文章

  • Swift5.1 - 枚举enum(4)

    1. 枚举的基本用法 使用 enum 关键词来定义 枚举; 2. 关联值 有时会将枚举的成员值跟 其他类型 的关联...

  • swift3语法(八)

    枚举/结构体 枚举 定义形式enum 枚举名 { 枚举值} // 例如enum CompassPoint {...

  • Rust 编程语言-6-枚举和模式匹配

    6. Enum和Pattern matching 6.1 Enum枚举 IP地址枚举 消息类型枚举:可以看到枚举中...

  • 菜鸡学Swift3.0 12.枚举

    1. 枚举定义 enum 定义枚举类型 { case 枚举项 ... } 2.原始值 rawValue enum...

  • Swift Day03 枚举 可选项

    一、枚举 1. 枚举(enum)的基本写法? 2. 枚举(enum)的关联值(Associated Value)?...

  • Python_枚举

    一、枚举 Enum类 Python中所有枚举类型都是enum模块下的Enum类的子类。 枚举中的标识最好全部使用大...

  • 枚举学习

    java enum枚举类 enum(枚举)类介绍 **java枚举类是一组预定义常量的集合,使用enum关键字声明...

  • OC中枚举写法 以及 字符串类型枚举实现探索

    常见枚举写法 C语言模式的枚举写法:enum 普通【整型】枚举写法 :NS_ENUM 位移枚举 :NS_OPTIO...

  • Swift5.1学习随笔之枚举enum

    Swift的枚举非常强大好用 如果变量有固定几种取值,建议用枚举 基本用法 关联值 Associated Valu...

  • 枚举: 使用小汇总

    枚举enum是同class,interface同一级别的特性。 枚举enum不能被继承。 枚举示例: 有人说枚举就...

网友评论

    本文标题:Swift5.1 - 枚举enum(4)

    本文链接:https://www.haomeiwen.com/subject/mtmzqctx.html