3

I read the document about Swift 5.1 from swift.org and have some questions about access level in enumeration.

https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#ID14

In the document, it says:

The individual cases of an enumeration automatically receive the same access level as the enumeration they belong to.

private enum SomePrivateEnum {
    case one
    case two
    case three
}

private class SomePrivateClass {
    private var somePrivateProperty = 0
}


// work
print(SomePrivateEnum.one)

// error: 'somePrivateProperty' is inaccessible due to 'private' protection level
print(SomePrivateClass().somePrivateProperty)


According to the document, if I have a private enum, then all cases should receive private access level. The question is, why can I access the private case outside the enum declaration ? This behavior is different from Class.

Hamish
  • 78,605
  • 19
  • 187
  • 280
yunhao
  • 94
  • 5
  • At the top level of a file, `private` is effectively `fileprivate`, therefore both the enum and its cases are only accessible within the file that defined it. Related: https://stackoverflow.com/q/43503274/2976878. – Hamish Jun 17 '19 at 11:12
  • @Hamish I assume the point to take home here is that while an enumeration groups a number of values together it is not a scope of its own like a struct or class or a file? – Joakim Danielson Jun 17 '19 at 11:39
  • 1
    @JoakimDanielson An enum is a scope, the documentation is just a bit misleading. When it says "receive the same access level as" what it really means is "is accessible within the same scope as". It's just like if you had written `private class SomePrivateClass { var someProperty = 0 }` – `someProperty` is accessible anywhere `SomePrivateClass` is, which in this case is anywhere within the file that defined it. – Hamish Jun 17 '19 at 11:47

2 Answers2

1

First of all, your code is completely artificial, as it would not even compile except in a playground — and in a playground the concepts of privacy are more or less meaningless. Test only within a real project.

When you do, you will have something like this:

private enum SomePrivateEnum {
    case one
    case two
    case three
}
private class SomePrivateClass {
    private var somePrivateProperty = 0
}
class ViewController : UIViewController {
    func test() {
        print(SomePrivateEnum.one)
        print(SomePrivateClass().somePrivateProperty)
    }
}

Now that we've established that, we can proceed to what's wrong with your test itself, namely that you are comparing apples with oranges. Here's the parallelism:

    print(SomePrivateEnum.one) // ok
    print(SomePrivateClass()) // ok

So private for SomePrivateEnum and private for SomePrivateClass mean the same thing, namely: "private within this file". This code is in the same file so it can see both SomePrivateEnum and SomePrivateClass. (As the docs tell you, code that can see SomePrivateEnum can see SomePrivateEnum.one, and vice versa. So we are now comparing apples with apples.)

But private for somePrivateProperty means something else. It means "private within this type". So only code inside SomePrivateClass can see somePrivateProperty. This code is not inside SomePrivateClass, so it can't see that property.

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

You can access private declarations inside current context. for example, if you wrap enum with other context - it will not be accessible same way as property inside SomePrivateClass.

i.e. this will be inaccessible:

struct Foo {
    private enum SomePrivateEnum {
        case one
        case two
        case three
    }
}
print(Foo.SomePrivateEnum.one)

and this will be:

private class SomePrivateClass {
    var somePrivateProperty = 0
}
print(SomePrivateClass().somePrivateProperty)
Kirow
  • 1,077
  • 12
  • 25