Swift枚举案例访问级别

时间:2017-11-13 00:57:16

标签: swift enums functional-programming access-levels

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

2 个答案:

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

还要确保枚举确实比结构或对象好。