Swift 枚举案例访问级别

Swift enum case access level

我知道,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 个具有非法高度的案例。如果可以覆盖案例的访问级别,或者允许在枚举中存储常量,则此问题将得到解决。

Swift switch 语句必须详尽无遗。假设您的 public enum Foo 的消费者试图在 switch 中使用它。如果 .bar 案例是私人的,那么 switch 应该如何处理它?

个案是枚举 public API 的一部分。如果您希望将它们设为私有,请将它们包装在一个仅公开 public 操作的结构中。

更新:随着 Swift 5 中 SE-0192 的实施,引入了 @unknown default: 语法。这在您有一个 enum 的情况下很有用,您已经处理了所有当前存在的案例,但希望通过指定 default 行为来保护自己免受将来添加的案例的影响。

您可以 'implement' 通过使用私有构造函数添加类型来实现该行为。

这是一个例子:

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)
}

还要确保枚举真的比结构或对象更好。