Visibility Modifiers
Visibility modifiers are keywords — public , private , protected , and internal — that control which parts of your code can see and use a declaration.
Learn Visibility Modifiers in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Used well, they enforce encapsulation: hiding internal state so an object can only be changed through the safe operations you choose to expose.
What You'll Learn in This Lesson
1️⃣ public (Default) & Top-Level private
If you write no modifier, a declaration is public — visible everywhere. At the top level of a file, private limits a function or property to that single file, which is great for small helpers you don't want leaking out.
2️⃣ private Inside a Class
Inside a class, private hides a member from the outside world — only the class's own methods may touch it. This is the heart of encapsulation: callers interact through public methods like deposit , never with the raw field.
3️⃣ Encapsulation & protected
A common pattern is a private backing field exposed through a read-only getter : the outside can read the value but never assign it, so all changes flow through your controlled methods.
The protected modifier is like private , but it also lets subclasses see the member:
Your turn. Fill in the ___ blank, then run and compare.
Mini-Challenge: Encapsulated Thermostat
Hide the temperature behind a private field and expose only safe operations. Warming once (+5) then cooling once (-5) returns to the start.
Common Errors (and the fix)
- ❌ "Cannot access 'balance': it is private in 'BankAccount'". ✅ Add a public method or getter instead of touching the field directly.
- ❌ Marking everything public and exposing raw mutable fields. ✅ Keep state private ; expose controlled operations.
- ❌ Expecting protected to be visible to unrelated callers. ✅ protected is only for the class and its subclasses.
- ❌ Assigning to a property that has only a getter. ✅ Add a setter, or mutate through a method like increment() .
Pro Tips
- 💡 Default to private for fields and open up only what callers truly need.
- 💡 private set : var x = 0; private set gives public reads but private writes.
- 💡 internal is your friend in libraries — public inside the module, hidden outside.
📋 Quick Reference — Visibility
Modifier
Who can see it
public
Everywhere (the default)
private (class)
Only the same class
private (top level)
Only the same file
protected
The class and its subclasses
internal
The same module
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ public is the default — visible everywhere
- ✅ private means same class, or same file at the top level
- ✅ protected adds visibility to subclasses
- ✅ internal limits visibility to the module
- ✅ Encapsulate with private fields and read-only getters
- ✅ Next lesson: Destructuring Declarations
Practice quiz
Which visibility is the default in Kotlin when no modifier is written?
- private
- internal
- protected
- public
Answer: public. Declarations are public by default, visible everywhere.
How many visibility modifiers does Kotlin have?
- Two
- Four
- Three
- Five
Answer: Four. They are public, private, protected, and internal.
Inside a class, what does private restrict a member to?
- Only code within that same class
- The whole module
- Subclasses too
- The whole file
Answer: Only code within that same class. A private class member is visible only inside that class.
At the top level of a file, what does private limit a declaration to?
- The whole package
- Subclasses
- The same file
- Nothing, it stays public
Answer: The same file. A private top-level declaration is visible only within that file.
What does protected add compared to private?
- Visibility to the entire module
- Visibility everywhere
- Nothing different
- Visibility to subclasses as well
Answer: Visibility to subclasses as well. protected is like private but also visible to subclasses.
What does internal restrict visibility to?
- A single class
- The same compilation module
- A single function
- Only subclasses
Answer: The same compilation module. internal makes a declaration visible everywhere within the same module.
What is the core idea of encapsulation?
- Hiding internal state behind a controlled interface
- Making every field public
- Avoiding classes entirely
- Using only top-level functions
Answer: Hiding internal state behind a controlled interface. Encapsulation hides state and exposes only safe operations.
How do you expose a private field as read-only to the outside?
- Make the field public
- Use a var with no type
- Provide a public getter with no setter
- Use protected
Answer: Provide a public getter with no setter. A private backing field plus a get-only property allows reads but not writes.
Can protected members be accessed by unrelated outside callers?
- Yes, always
- Yes, within the module
- Only via reflection
- No, only the class and its subclasses
Answer: No, only the class and its subclasses. protected is limited to the declaring class and its subclasses.
What does var x = 0; private set achieve?
- Makes x fully private
- Public reads but private writes
- Deletes the getter
- Makes x a val
Answer: Public reads but private writes. A private setter lets outside code read but not assign the property.
Continue this course
- Previous: Type Checks & Smart Casts
- Next: Destructuring Declarations