一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情。
前面说完了 Single-payload enums , 接下来我们说第三种情况 Mutil-payload enums , 有多个负载的情况产生时,当前的 enum是如何进行布局的哪?
enum ZGEnum {
case test_one(Bool)
case test_two(Bool)
case test_three
case test_four
}
print(MemoryLayout<ZGEnum>.size)
print(MemoryLayout<ZGEnum>.stride)
var a = ZGEnum.test_one(false)
var b = ZGEnum.test_two(true)
var c = ZGEnum.test_three
var d = ZGEnum.test_three
var f = ZGEnum.test_four
1
1
上面这个例子中,我们有两个 **Bool 类型**的负载,这个时候我们打印当前的 enum 大小 发现其大小仍然为 1,这个时候我们来看一下内存当中的存储情况。
这里我们可以看到当前内存存储的分别是 00 41 80 80 81 00 , 这里在存储当前的 case 时候会使用到 common spare bits,什么意思?其实在上一个案例我们也讲过了,首先 bool 类型需要 1 字节,也就是 8 位。
接下来我们来看一下 00 41 80 80 81 00 分别代表的是什么?首先 0, 4, 8 这里我们叫 做 tag value , 0, 1 这里我们就做**tag index**。
当前一般来说,我们有多个负载的枚举时,当前枚举类型的大小取决于当前最大关联值的大小。
递归枚举
递归枚举其实就是使用递归的方式来进行数据描述。使用**indirect**关键字修饰的枚举值表示这个枚举值是可递归的,即此枚举值中的相关值可以使用其枚举类型本身。
enum Expression {
case num(num: Int)
indirect case add(num1: Expression, num2: Expression)
indirect case sub(num1: Expression, num2: Expression)
indirect case mul(num1: Expression, num2: Expression)
indirect case div(num1: Expression, num2: Expression)
}
使用Expression枚举来描述复合表达式 ( (5 + 5) * 2 - 8) / 2的代码如下:
///单值 5
var num5 = Expression.num(num: 5)
/// 表达式 5 + 5
var exp1 = Expression.add(num1: num5, num2: num5)
///单值 2
var num2 = Expression.num(num: 2)
///表达式 (5 + 5) * 2
var exp2 = Expression.mul(num1: exp1, num2: num2)
///单值 8
var num8 = Expression.num(num: 8)
///表达式 (5 + 5) * 2 - 8
var exp3 = Expression.sub(num1: exp2, num2: num8)
///表达式 ((5 + 5) * 2 - 8) / 2
var expFinal = Expression.div(num1: exp3, num2: num2)
我们可以为这个四则表达式枚举类型Expression实现一个函数来进行运算,在开发中将描述与运算结合,能够编写出十分优美的代码。处理递归枚举通常会采用递归函数,函数方法实现示例如下:
func expressionFunc(num: Expression) -> Int {
switch num {
case let .num(num):
return num
case let .add(num1, num2):
return expressionFunc(num: num1) + expressionFunc(num: num2)
case let .sub(num1, num2):
return expressionFunc(num: num1) - expressionFunc(num: num2)
case let .mul(num1, num2):
return expressionFunc(num: num1) * expressionFunc(num: num2)
case let .div(num1, num2):
return expressionFunc(num: num1) / expressionFunc(num: num2)
}
}
///((5 + 5) * 2 - 8) / 2 打印结果为6
expressionFunc(num: expFinal)
关于递归枚举还有一点需要注意,如果一个枚举中所有的枚举值都是可递归的,开发者可以直接将整个枚举类型声明为可递归的,示例如下:
indirect enum Expression {
case num(num: Int)
case add(num1: Expression, num2: Expression)
case sub(num1: Expression, num2: Expression)
case mul(num1: Expression, num2: Expression)
case div(num1: Expression, num2: Expression)
}