欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

04-枚举

程序员文章站 2024-03-23 10:01:52
...
  • 枚举的基本用法

enum Direction {
    case north
    case south
    case east
    case west
}
enum Direction {
    case north, south, east, west
}

var dir = Direction.west
dir = Direction.east
dir = .north
print(dir) // north

switch dir {
case .north:
    print("north")
case .south:
    print("south")
case .east:
    print("east")
case .west:
    print("west")
}
  • 关联值(Associated Values)

有时将枚举的成员值其他类型的值关联存储在一起, 会非常有用

enum Score {
    case points(Int)
    case grade(Character)
}

var score = Score.points(96)
score = .grade("A")
switch score {
case let .points(i):
    print(i, "points")
case let .grade(i):
    print("grade", i)
}
// 打印结果:grade A。
// 注意:其实 i 就是 字符串 "A",'let .grade(i)'相当于拿到枚举中 grade 这个成员值与它关联的值 'A'
enum Date {
    case digit(year: Int, month: Int, day: Int)
    case string(String)
}

var date = Date.digit(year: 2020, month: 6, day: 4)
date = Date.string("2020-6-4")

switch date {
case .digit(let year, let month, let day):
    print("\(year)-\(month)-\(day)")
case let .string(vaule):
    print(vaule)
}
  • 关联值举例

04-枚举

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

var pwd = Password.number(3, 5, 7, 8)
pwd  = .gesture("12369")

switch pwd {
case .number(let n1, let n2, let n3, let n4):
    print(n1, n2, n3, n4)
case let .gesture(vaule):
    print(vaule)
}
  • 原始值(Raw Values)

枚举成员可以使用相同类型的默认值预先对应,这个默认值叫做:原始值。

enum PokerSuit: Character {
    case spade = "♠️"
    case heart = "❤️"
    case diamond = "♦️"
    case club = "♣️"
}

var suit = PokerSuit.spade
print(suit) // spade
print(suit.rawValue) // ♠️
print(PokerSuit.club.rawValue) // ♣️
enum Grade: String {
    case perfect = "A"
    case great = "B"
    case good = "C"
    case bad = "D"
}

print(Grade.perfect.rawValue)   // A
print(Grade.great.rawValue)     // B
print(Grade.good.rawValue)      // C
print(Grade.bad.rawValue)       // D

注意:原始值不占用枚举变量的内存

  • 隐私原始值(Implicitly Assigned Raw Values)

如果枚举的原始值类型是 Int, String 类型,Swift 会自动分配原始值

enum Direction: String {
    case north = "north"
    case south = "south"
    case east = "east"
    case west = "west"
}

上面这种写法等价于下面这种写法

enum Direction: String {
    case north, south, east, west
}
print(Direction.north) // north
print(Direction.north.rawValue) // north
  • Int 类型的枚举,如果不去指定枚举中某个成员的原始值,它的原始值从 0 开始依次往上增加
enum Season: Int {
    case spring, summer, autumn, winter
}

print(Season.spring.rawValue)       // 0
print(Season.summer.rawValue)       // 1
print(Season.autumn.rawValue)       // 2
print(Season.winter.rawValue)       // 3
  • Int 类型的枚举,如果指定枚举中某个成员的原始值,它的原始值就会从指定的值开始依次往上增加,如果后面再有指定成员的原始值是某个值,它又会从指定的值开始依次往上增加
enum Season: Int {
    case spring = 1, summer, autumn = 4, winter
}

print(Season.spring.rawValue)       // 1
print(Season.summer.rawValue)       // 2
print(Season.autumn.rawValue)       // 4
print(Season.winter.rawValue)       // 5

注意:枚举中的原始值不能有重复的,否则会报错

  • 递归枚举

indirect enum ArithExpr {
    case number(Int)
    case sum(ArithExpr, ArithExpr)
    case difference(ArithExpr, ArithExpr)
}

下面这些写法等价于上面这种写法

enum ArithExpr {
    case number(Int)
    indirect case sum(ArithExpr, ArithExpr)
    indirect case difference(ArithExpr, ArithExpr)
}
let five = ArithExpr.number(5)
let four = ArithExpr.number(4)
let tow = ArithExpr.number(2)
let sum = ArithExpr.sum(five, four)
let difference = ArithExpr.difference(sum, tow)

func calculate(_ expr: ArithExpr) -> Int {
    switch expr {
    case let .number(vaule):
        return vaule
    case let .sum(left, right):
        return calculate(left) + calculate(right)
    case let .difference(left, right):
        return calculate(left) - calculate(right)
    }
}

print(calculate(difference)) // 7
  • MemoryLayout

可以使用MemoryLayout 获取数据类型占用内存的大小

enum Password {
    case number(Int, Int, Int, Int)
    case other
}

MemoryLayout<Password>.stride       // 40 分配占用空间的大小
MemoryLayout<Password>.size         // 33 占用空间的大小
MemoryLayout<Password>.alignment    // 8  内存对齐

在 Password 枚举中,number 在 64 位系统下占用 32 个字节(因为 Int 类型在 64 位系统下占用 8 个字节),other 占用 1 个字节。所以 Password 这个枚举共占用 33 个字节,由于内存对齐是 8 个字节,所以系统会分配 40 个字节的空间给 Password 存,但实际上 Password 只用 33 个字节就够了。

var pwd = Password.number(9, 8, 6, 4)
pwd = .other

MemoryLayout.stride(ofValue: pwd)       // 40
MemoryLayout.size(ofValue: pwd)         // 33
MemoryLayout.alignment(ofValue: pwd)    // 8

本文章只是本人的学习笔记!