Access Control
Decide who can see and use each part of your code with Swift's five access levels — open , public , internal , fileprivate , and private — to hide implementation details and present a clean, deliberate interface.
Learn Access Control in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- • The five levels: open , public , internal , fileprivate , private
- • Why internal is the default
- • The difference between private and fileprivate
- • What open adds over public (subclassing across modules)
- • Read-only-from-outside properties with private(set)
- • How to encapsulate internals behind a safe public surface
1️⃣ The Five Levels in Action
From widest to narrowest: open , public , internal , fileprivate , private . The classic pattern is a public type with private internals, exposing only safe methods.
2️⃣ internal — The Default
Write no modifier and you get internal : usable anywhere in the same module. This is what the vast majority of app code wants, so you only annotate when you need to go tighter or wider.
3️⃣ private(set), private vs fileprivate
private(set) gives you a property others can read but only your own code can write — perfect for protected state. And remember: private is scoped to the enclosing declaration (plus same-file extensions), while fileprivate opens up to the whole file.
Your turn. Fill in the setter modifier and the most restrictive level.
Pro Tips
- 💡 Start private , widen as needed. The less you expose, the easier code is to change safely.
- 💡 Use private(set) for state that's safe to read but should only be mutated internally.
- 💡 Reserve open for framework classes you intend others to subclass.
- 💡 A public API can't leak an internal type — keep its signature types at least as accessible.
Common Errors (and the fix)
- "'x' is inaccessible due to 'private' protection level": you touched a private member from outside. Add a method, or relax the level.
- "... cannot be declared public because its ... uses an internal type": a public API leaked a less-accessible type. Make that type public too.
- "Cannot assign to property: setter is inaccessible": the property uses private(set) . Mutate it through a method instead.
- "Cannot inherit from non-open class outside of its module": the class is public , not open . Mark it open to allow subclassing.
📋 Quick Reference
Level
Visible
Subclass outside module?
open
other modules
yes
public
no
internal
same module (default)
n/a
fileprivate
same file
private
enclosing declaration
Frequently Asked Questions
Mini-Challenge: Temperature Sensor
No blanks this time — just a brief and an outline. Encapsulate the calibration and expose only a read-only reading.
Practice quiz
What is the default access level in Swift when you write none?
- private
- public
- internal
- open
Answer: internal. If you omit an access modifier, the entity is 'internal' — visible anywhere within the same module.
Which access level restricts use to the same source file?
- fileprivate
- private
- internal
- public
Answer: fileprivate. 'fileprivate' makes an entity accessible only within the file it is declared in.
How does 'private' differ from 'fileprivate'?
- They are identical
- private is broader
- private allows subclassing
- private limits to the enclosing declaration (and its extensions in the same file); fileprivate limits to the whole file
Answer: private limits to the enclosing declaration (and its extensions in the same file); fileprivate limits to the whole file. private is tighter — scoped to the enclosing type/declaration, while fileprivate covers the entire file.
What does 'internal' mean?
- Visible only in the type
- Visible anywhere within the same module
- Visible to any module
- Visible only in subclasses
Answer: Visible anywhere within the same module. internal entities are accessible throughout the defining module but not from other modules.
What can 'open' do that 'public' cannot?
- Allow subclassing and overriding from outside the defining module
- Nothing, they are the same
- Restrict access to a file
- Make members private
Answer: Allow subclassing and overriding from outside the defining module. open lets other modules subclass a class and override its members; public exposes but does not permit external subclassing/overriding.
Which is the MOST restrictive access level?
- fileprivate
- internal
- private
- public
Answer: private. private is the most restrictive, limiting access to the enclosing declaration.
Order these from most open to most restrictive.
- private, fileprivate, internal, public, open
- open, public, internal, fileprivate, private
- internal, public, open, private, fileprivate
- public, open, internal, private, fileprivate
Answer: open, public, internal, fileprivate, private. From most to least open: open, public, internal, fileprivate, private.
Can a public function have a parameter of an internal type?
- Yes, always
- Only with open types
- Only inside extensions
- No — a public API cannot expose a less-accessible type in its signature
Answer: No — a public API cannot expose a less-accessible type in its signature. An entity cannot be more accessible than the types it uses in its public interface.
What is a common use of 'private(set)' on a property?
- Make it fully public
- Allow reading from anywhere but only setting within the declaring scope
- Hide it completely
- Make it open
Answer: Allow reading from anywhere but only setting within the declaring scope. private(set) gives a property a public (or internal) getter but a private setter — read freely, write internally.
Why use access control at all?
- To make code run faster
- It is required for every declaration
- To hide implementation details and expose a clean, intentional interface
- To enable optional chaining
Answer: To hide implementation details and expose a clean, intentional interface. Access control encapsulates internals, reducing coupling and protecting invariants behind a deliberate public surface.
Continue this course
- Previous: Type Casting (is, as?)
- Next: Memory Management & ARC