-
- 1.1. Example
- 1.2. Why the indirect Keyword Is Necessary
- 1.3. Conclusion
1. Understanding Recursive Enumerations in Swift
什么是递归枚举?“间接”关键字做什么?
递归枚举只不过是一种枚举,其case指向枚举本身。
要创建一个,您需要使用indirect关键字。例如:
enum Test {
indirect case value(Test)
}
你也可以把间接关键字放在枚举声明的前面:
indirect enum Test {
case value(Test)
}
***indirect***关键字用于告诉Swift以一种允许其增长的方式存储这种特殊类型的枚举。
1.1. Example
让我们创建一个递归枚举示例。在本例中,您将使用形状。
点是最简单的形状。如果你把两个点连起来,你会得到一条同样是形状的直线。 所以两个形状可以用来构造一个新形状。因此,形状需要是递归构造。
有很多方法可以将其转换为代码,但让我们使用递归枚举:
enum Shape {
case Point(Double, Double)
indirect case Line(Shape, Shape)
func info() -> String {
switch self {
case .Point(let x, let y):
return "(\(x), \(y))"
case .Line(let p1, let p2):
return p1.info() + " <---> " + p2.info()
}
}
}
让我们仔细看看代码:
-
关键是Shape枚举同时表示点和线。 但由于Line也是Shape,它需要递归地引用Shape。这是通过间接案例Line(Shape, Shape)实现的。
-
info()方法只是创建形状的字符串表示。 让我们通过创建三个形状来测试以上内容:两个点和由这些点连接的一条线。
let pStart: Shape = Shape.Point(3.08, 4.23)
let pEnd: Shape = Shape.Point(7.12, 9.32)
let line: Shape = Shape.Line(pStart, pEnd)
print(line.info())
输出是一个从点"(3.0,4.23)"到"(7.12,9.32)"的"行",以字符串形式表示:
(3.0, 4.23) <---> (7.12, 9.32)
1.2. Why the indirect Keyword Is Necessary
如果创建一个没有indirect关键字的递归枚举:
enum Test {
case value(Test)
}
你会得到一个编译错误:recursive enum 'Test' is not marked 'indirect'。
在Swift中,枚举本质上是值类型。这意味着必须在编译期间对它们的内存进行管理。简单地说,必须事先知道枚举所需的确切内存大小。
记住这一点,如果您创建一个递归枚举(即在它内部引用枚举本身),那么您创建的递归是不可能说出枚举需要多少内存的。
这个问题可以通过间接关键字来解决。通过这样做,您告诉Swift更改存储枚举的方式,以允许它的大小增长。
1.3. Conclusion
递归枚举是一种特殊类型的枚举,它可以引用自身。你可以像普通枚举一样创建一个,但是由于Swift的内存管理原因,你需要使用indirect关键字。
For example:
enum Test {
indirect case value(Test)
}