我知道,Swift不允许在枚举中重新定义案例的访问级别,这意味着以下是不可能的
public enum Foo {
private case Bar
private indirect case Ind(Foo)
public init() {
self = Bar
}
}
谁能告诉我为什么不允许这样做?在某些情况下,隐藏枚举的情况并提供启动此类情况的初始化程序是切实可行的,因此我并没有真正看到禁止此功能的动机。
考虑以下纯功能树结构的示例:
public enum Tree<T: Comparable> {
case Leaf
indirect case Node(T, Tree, Tree, Int)
public init() {
self = .Leaf
}
public func height() -> Int {
switch self {
case .Leaf:
return 0
case let .Node(_, _, _, h):
return h
}
}
// functions for add and remove, etc.
}
为了更好的运行时(实现自平衡二叉树时需要),可能希望将树的高度包含在Node
情况下的关联值中。但是这给出了封装问题,因为现在可能会构造具有非法高度的Node
个案例。如果可以覆盖案例的访问级别,或者如果允许在枚举中存储常量,则可以解决此问题。
答案 0 :(得分:3)
Swift switch
陈述必须是详尽无遗的。假设您public enum Foo
的消费者试图在switch
中使用它。如果.bar
案例是私有的,那么switch
应该如何处理呢?
案例是枚举的公共API的一部分。如果您希望将它们设为私有,请将它们包装在仅公开公共操作的结构中。
答案 1 :(得分:0)
您可以通过使用私有构造函数添加类型来“实现”该行为。
这里是一个例子:
public enum Foo {
case a(Barrier)
case b(Int, Int, Barrier)
public init(x: X?) {
if let x: X = x {
self = .b(x.y, x.z, Barrier())
} else {
self = .a(Barrer())
}
}
/// Use Foo constructor!
public struct Barrier {
fileprivate init() { }
}
}
有些人仍然可以创建没有任何意义但看起来很乏味的实例:
func createB() -> Foo {
switch Foo(x: nil) {
case .a(let barrier): return Foo.b(1, 2, barrier)
case .b(_, _, let barrier): return Foo.b(1, 2, barrier)
}
还要确保枚举确实比结构或对象好。