3

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

4

2 回答 2

3

Swiftswitch语句必须是详尽无遗的。假设您的消费者public enum Foo尝试在switch. 如果.bar案件是私人案件,switch应该如何处理?

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

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

于 2017-11-13T01:12:34.383 回答
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)
}

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

于 2019-10-24T15:12:49.340 回答