美文网首页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)

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