
C# and Java programmers are used to working with class member access level modifiers like public, private, and protected. With the latest version of Swift (which came with the latest version of Xcode), we got access level modifiers too. They’re just a little bit different.
Prior to Xcode beta 4, there was one and only one level of access in Swift. Now there are three:
private– accessible only from within the source file where it’s defined,internal– accessible only from any file within the target where it’s defined, andpublic– accessible from any file within the target where’s it’s defined, and from within any other context that imports the current target’s module.
In case you’re not clear on what’s meant by a target: it’s the end result of doing a build in Xcode. For most of us, this is likely an app, but it could also be a library, framework or unit test bundle.
These levels of access are file-based rather than class-based. To help make things clear, I’ve put together some illustrations.
The default access level: internal
The first level of access I’ll cover is internal…

An internal entity can be “seen” within the file where it’s defined, as well as from any other file in the same application or framework.
internal is the default level of access, and the only access level in versions of Swift prior to beta 4. If an entity — that is, a variable, constant, enum, struct, or class — doesn’t have a specified access level, its access level is internal.
The locked-down access level: private
The next level of access is private…

A private entity can be “seen” within the file where it’s defined, and only within that file. It’s invisible from outside that file.
If you’re used to the sort of access C# or Java programmer, you’re used to the idea of a private entity being one that can’t be “seen” outside the class. In Swift, access level is about files, not classes, meaning that a Swift private entity is one that can’t be seen outside its own file. Two Swift classes in the same file would be able to access each other’s private variables, methods, and so on. This approach will make it possible to encapsulate related classes in a single file, with “internal use only” classes marked as private. It also gets around having to use access kludges like C++’s friend functions and classes.
The “putting myself out there” access level: public
Just as private is a little bit different from what you might expect, so is public…

A public entity can be “seen” within the file where it’s defined, from any other file in the same application or framework, and by another file any other application or framework that imports the application or framework where the public entity was defined.
Once again, if you’re a C# or Java programmer, this may seem weird. Swift’s internal is closest in spirit to C#’s and Java’s public; Swift’s public exposes entities to outside code that imports our application or framework. This should come in particularly handy for those of you who are writing libraries: you can choose which classes and methods to expose to clients by marking them as public.
Trying out the new access levels
The following is a copy-and-paste from some code I wrote while taking these new access levels for a spin. I created a file called RelatedClasses.swift that contain classes named SomeClass, SomeOtherClass, and HiddenClass:
// RelatedClasses.swift
class SomeClass {
internal func doSomethingInternal() -> () {
println("SomeClass::doSomethingInternal() called.")
}
func doSomethingDefault() -> () {
println("SomeClass::doSomethingDefault() called.")
}
private func doSomethingPrivate() -> () {
println("SomeClass::doSomethingPrivate() called.")
}
}
class SomeOtherClass {
let someClassInstance = SomeClass()
private let hiddenClassInstance = HiddenClass()
func usePrivateMethodInSameFileDifferentClass() -> () {
someClassInstance.doSomethingPrivate()
}
}
private class HiddenClass {
}
Note that:
SomeClasshas two internal methods:doSomethingInternal()anddoSomethingDefault().doSomethingInternal()‘sinternalaccess level is explicit, anddoSomethingDefault()‘sinternalaccess level is explicit. Both these methods are callable from inside RelatedClasses.swift, or from any file inside the application or framework containing RelatedClasses.swift.SomeClassalso has aprivatemethod:doSomethingPrivate(). It’s accessible from withinSomeClass, but also from anywhere else inside RelatedClasses.swift, including from within the other two classes. You can’t call this method from outside RelatedClasses.swiftSomeOtherClasscontains an instance ofSomeClassandHiddenClass. Note that becauseHiddenClassisprivate, any instance ofHiddenClassmust also be declaredprivate.SomeOtherClasshas a method with the rather long nameusePrivateMethodInSameFileDifferentClass(), and it lives up to its name. It can accessSomeClass'doSomethingPrivate()method even though it’sprivatebecause it’s in the same file, and Swift’s access control is more file-based than class hierarchy-based.HiddenClassis aprivateclass. SinceSomeClassandSomeOtherClassare in the same file, they can “see” it and create instances of it. Its definition is “invisible” outside the file, and thus you can’t create aHiddenClassinstance outside of RelatedClasses.swift.
As you can see, Swift’s access control is different from C#’s and Java’s, which will lead to different coding patterns. We typically see the one-class-per-file approach in C# and Java, but Swift’s different kind of private access will likely give rise to larger-scale type of encapsulation, with related classes in the same file. public may change the way people write libraries and frameworks — I’m more of a library/framework user than a writer, so I’ll leave it to others to deliver more informed comment on that. It’ll be interesting to see the approaches that programmers come up with as they use Swift.
Recommended Reading
The online Swift documentation has been updated to cover the addition of access control in beta 4. There’s also some interesting discussion about Swift’s access levels in the Human Friendly’s blog, in an article titled Swift Access Controls are like C’s (and that isn’t necessarily a bad thing).


















