Reputation: 649
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.
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.
Upvotes: 3
Views: 5248
Reputation: 439
You can 'implement' that behaviour by adding type with private constructor.
Here is an example:
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() { }
}
}
Someone still can create instance that doesn't make any sense but will look tedious:
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)
}
Also make sure that enums are really better than structs or objects.
Upvotes: 0
Reputation: 63369
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.
Upvotes: 3