Search code examples
swiftenumsfunctional-programmingaccess-levels

Swift enum case access level


I know, that Swift does not allow redefinition of the access level of a case in a enum, meaning the following is not possible

public enum Foo {
    private case Bar
    private indirect case Ind(Foo)
    public init() {
        self = Bar
    }
}

Can anyone tell me why this is not allowed? There are some scenarios, where it is practical to hide cases of a enum and providing a initializer that initiates to such a case, therefore I don't really see the motivation to disallow this feature.

Edit:

Consider the following example of a purely functional tree structure:

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

For better runtime (which is desirable when implementing self-balancing binary trees), one might want to include the height of the tree as an associated value in the Node case. But this gives encapsulation problems, as one might now construct Node cases with illegal heights. This problem would be solved if the access level of the case could be overwritten, or if stored constants in enums would be allowed.


Solution

  • Swift switch statements must be exhaustive. Suppose a consumer of your public enum Foo tries to use it in a switch. If the .bar case is private, how is the switch supposed to handle it?

    Cases are part of the public API of an enum. If you wish to make them private, wrap them in a struct that exposes only public operations.

    Update: With the implementation of SE-0192 in Swift 5, the @unknown default: syntax was introduced. This is useful in situations where you have a enum for which you've handled all currently existing cases, but want to protect yourself from future cases being added, by specifying the default behaviour.