What is the purpose of access control? List the levels.
Predict first
Does this compile? (both in the same file)
struct Account {
private var balance = 0
}
extension Account {
func show() -> Int { balance }
}
- Yes
- No — balance is private
Mental model. Each level is a fence with a different radius. Start with the smallest fence that still contains the people who need in.
Access control limits who can depend on a declaration — it is how you keep an API small while keeping implementation details free to change.
private— the enclosing declaration (and extensions in the same file).fileprivate— the whole file.internal— the module (the default).package— every target in the same SPM package (Swift 5.9).public— any importer, but not overridable/subclassable outside the module.open— importers may subclass and override. Classes only.
Since Swift 4, private is visible to extensions of the same type in the same file. A different file would need fileprivate or wider.
Common traps
- Making everything
public“just in case”. Every public symbol is a compatibility promise you now have to keep. - Using
fileprivatewhenprivatewould do. It widens the surface to every declaration in the file, which is rarely needed now thatprivateworks across same-file extensions.
They might follow up with
- Does
privatework across extensions? Yes, for extensions of the same type in the same file. In another file, no. - What about
internaland@testable import? That is why test targets can reach internal members — do not make things public just to test them.