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)
}
还要确保枚举真的比结构或对象更好。
我知道,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)
}
还要确保枚举真的比结构或对象更好。