Swift枚举案例访问级别

Swift枚举案例访问级别,swift,enums,functional-programming,access-levels,Swift,Enums,Functional Programming,Access Levels,我知道,Swift不允许在枚举中重新定义案例的访问级别,这意味着以下操作是不可能的 public enum Foo { private case Bar private indirect case Ind(Foo) public init() { self = Bar } } 有人能告诉我为什么这是不允许的吗?在某些情况下,隐藏枚举的案例并提供初始化器来初始化此类案例是可行的,因此我并不认为有什么动机不允许此功能 编辑: 考虑以下纯功能树结构的示

我知道,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.
}
公共枚举树{
箱叶
间接事例节点(T,Tree,Tree,Int)
公共init(){
self=.Leaf
}
公共函数高度()->Int{
切换自身{
案例.叶:
返回0
案例let.Node(u,u,h):
返回h
}
}
//添加和删除等功能。
}

为了更好地运行(这在实现自平衡二叉树时是可取的),可能需要将树的高度作为关联值包含在
节点
案例中。但这会带来封装问题,因为现在可能会构造高度非法的
节点
案例。如果可以覆盖案例的访问级别,或者允许在枚举中存储常量,则可以解决此问题。

Swift
switch
语句必须详尽无遗。假设
public enum Foo
的使用者试图在
开关中使用它。如果
.bar
案例是私有的,
开关应该如何处理它

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


更新:随着Swift 5中的实现,引入了
@unknown default:
语法。这在以下情况下非常有用:您有一个
enum
,您已经为其处理了所有当前存在的案例,但希望通过指定
默认
行为来保护自己不受未来添加案例的影响。

您可以通过使用私有构造函数添加类型来“实现”该行为

以下是一个例子:

公共枚举Foo{
案例a(障碍物)
案例b(内部,内部,屏障)
公共初始化(x:x?){
如果设x:x=x{
self=.b(x.y,x.z,Barrier())
}否则{
self=.a(barler())
}
}
///使用Foo构造函数!
公共结构屏障{
fileprivate init(){}
}
}
有些人仍然可以创建没有任何意义但看起来乏味的实例:

func createB()->Foo{
开关Foo(x:nil){
案例a(让障碍物):返回Foo.b(1,2,障碍物)
case.b(u,u,let barrier):返回Foo.b(1,2,barrier)
}

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

你能给出一个示例用例吗?就我个人而言,我从来没有想过要这样做。如果你解释的话,可能还有另一种方法可以实现你想要的。包括一个示例。解决问题的一种可能性是将枚举包装在一个结构中,但这非常简单痛苦。在Swift中构建大量此类数据结构的实践中,更好的解决方案是将其嵌入一个以左/右为可选项的类中。我知道枚举是构建它的自然方式,如果不是枚举,则是结构,但一旦你沿着这条路走了一小段,它往往会爆炸得非常快。即使你想展示将其作为值类型使用,最终会在内部隐藏一个私有类(就像Array和Dictionary一样)。好吧,我明白你的意思。初始化时通常会出现问题。读取案例会很好,但在初始化过程中,你可能不想控制案例中的所有关联值(请参阅上面添加的示例)。当允许使用枚举存储常量时,也可以解决这一问题,但这是离题的…@tierriminator您首先不会真的想将树的节点建模为
枚举。有些操作只在整个树上执行,而不是在子树上执行(例如,写时复制、树平衡),因此您可能希望使用某种结构/类包装器来提供这些内容。枚举可以是私有的,并在内部用于提供此结构中的存储/class@tierriminatorLinkedlist就是一个类似的例子。你永远不会只想把对某个节点的引用交给客户端。你应该提供一个可以ds开始引用(和结束引用,如果是双链接列表),存储一个memonized
count
变量,并封装图下的节点:我同意OOP,但在函数式编程中,它看起来有点不同。你根本不想在FP中使用引用,这将打破FP的最基本原则,即它是无状态的。在这里,我只是在寻找一种优化e
height
查询PF树。如果swift支持纯函数,它将知道一旦计算,
height
将不再改变,也不需要进行此优化。这可能是多范例编程的缺点。“你根本不想在FP中使用引用。”这是不正确的。大多数FP语言只有引用。你只是没有注意到,因为它们是不可变的。让你的数据结构成为不可变的类,它会更紧密地遵循你期望的模式。Swift不是一种函数式语言;试图强迫它总是会导致眼泪和头发拉扯。在我的例子中,我们是创造性的ng enterprise product(应用程序和后端)。一些对象具有用于较新后端的附加字段,我们需要一个库来处理每个可能的后端。假设每个对象都有一个可能的字段列表,如果我们要求,后端将返回这些字段(字段实现为枚举)。大多数字段在所有后端之间共享,对于某些字段,我们通过