0

Quote from The Swift Programming Language (Swift 3.1):

Custom initializers can be assigned an access level less than or equal to the type that they initialize. The only exception is for required initializers (as defined in Required Initializers). A required initializer must have the same access level as the class it belongs to.

If so, why does this code compile and work?

private class GoofyClass {
    public init(mood: String) {}
    public required init(isCrazy: Bool) {}
}

private let shock = GoofyClass(mood: "shocked")
private let crazy = GoofyClass(isCrazy: true)
Robo Robok
  • 21,132
  • 17
  • 68
  • 126
  • Why shouldn't it? There isn't a superclass, right? And while declared as `public`, you have one `init(isCrazy:)` - looks good - and a second `init(mood:)`. The only thing I can see you're having problems with is something you haven't stated - the inits are `public` and the class is `private`. Yes, I'm surprised it builds (maybe it's a bug in Xcode 8.3 compiler?) but I don't think you'll easily crash your app trying to init a `private` class. –  Jul 12 '17 at 00:50
  • The only thing I mean here is `private` class and `public` initializers. That's why I posted the quote from the book. :) – Robo Robok Jul 12 '17 at 00:55
  • After further investigation, I found out that protocol's access levels behavior is different from the one stated in the book too. It might be a buggy compiler. – Robo Robok Jul 12 '17 at 00:59
  • Is this in a playground? Even if you declare a class as private, it's still accessible in the same playground file. – JAL Jul 12 '17 at 01:08
  • 1
    Yes, this is Playground. I understand that it's accessible in the same file, but does it explain the fact why the compiler allows to declare higher access level inside? – Robo Robok Jul 12 '17 at 01:14
  • You might need to clarify that in your question. I didn't know what you meant - but I'm no expert! :) I'd be really happy to hear is a buggy compiler. –  Jul 12 '17 at 02:12
  • That sounds like a compiler issue. – adev Jul 12 '17 at 03:32

1 Answers1

2

In Swift, members of a class or struct with a less restrictive access level than the class/struct itself are automatically downgraded to the same level as the class/struct. I believe this is a deliberate design decision on the part of the language designers.

In your case, assuming the class is declared at the top level in the file (i.e. it is not nested inside another type), the inits you have declared public are, in fact, fileprivate.

The only exception is for required initializers (as defined in Required Initializers). A required initializer must have the same access level as the class it belongs to.

This is referring to the fact that you cannot make the access level of a required initialiser more restrictive than its class e.g.

open class Foo 
{
    internal required init() // error
}
JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • I don't think it's true for explicit declarations. – Robo Robok Jul 12 '17 at 09:10
  • @RoboRobok Well the fact is that defining a public initialiser in a `fileprivate` class is not an error. – JeremyP Jul 12 '17 at 09:15
  • But it should be, according to the official book. Just like defining anything else with higher access level inside entity of lower access level is an error. – Robo Robok Jul 12 '17 at 09:19
  • @RoboRobok Compare [Why am I allowed method access less restrictive than class access?](https://stackoverflow.com/q/40289745/2976878) – being able to define members with a higher access level than the type they're defined in is useful for communicating the access level the members should have if the type is ever given a higher access level. These members still have an effective access level equivalent to the type's access level though, as JeremyP says. – Hamish Jul 12 '17 at 09:25
  • @RoboRobok If that is what the book says, the book is wrong. The behaviour is defined in [SE-0025](https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md) which takes precedence.(Thanks for the reference, @Hamish) – JeremyP Jul 12 '17 at 09:45
  • @JeremyP so it seems like the answer is: `This allows the designer of the type to select the access they would use were they to make the type more widely accessible.`. Am I right? – Robo Robok Jul 12 '17 at 09:52