What is the difference between public, private, and protected?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
public, private, and protected are access modifiers used to control who can use a class member. They are central to encapsulation because they let you decide which parts of a type are part of its external API and which parts stay internal to the implementation.
public Exposes Members Broadly
A public member is part of the type's visible interface. Other code can call it directly, which makes it appropriate for behavior you intentionally support for consumers.
The key tradeoff is that public APIs are harder to change later without breaking callers. Make something public only when you want other code to depend on it.
private Hides Implementation Details
private members are accessible only inside the same class. This is the default choice for state or helper methods that should not be touched from the outside.
Here, callers can deposit money, but they cannot bypass the validation logic. That is exactly what good encapsulation is supposed to achieve.
protected Allows Subclass Access
protected sits between public and private. In many object-oriented languages, a protected member is available inside the class and inside derived classes. In Java, it is also visible to classes in the same package.
This is useful when subclasses legitimately need access to extension points, but the member should not be part of the general public API.
The Meaning Depends on the Language
The general ideas are consistent, but details vary by language:
- Java
protectedalso includes package-level visibility - C#
protectedis for the type and subclasses, not the whole assembly - some languages add more modifiers such as
internal,fileprivate, or package-private defaults
So when you read advice about access modifiers, always map it to the actual language semantics you are working with.
How to Choose in Practice
A practical rule is:
- start with
private - widen to
protectedonly if subclasses need it - widen to
publiconly if outside callers need it
This "most restrictive first" approach keeps your API smaller and your refactoring options wider.
It also makes code easier to reason about. When fewer parts are exposed, fewer parts can be misused or coupled too tightly to current implementation details.
Design Example: Public Method, Private State
Good class design often combines a small public surface with private state and helpers.
Consumers get a clear public API, while validation details stay hidden and changeable.
Common Pitfalls
- Making fields public when access should go through validated methods.
- Using
protectedtoo freely and creating fragile inheritance-based coupling. - Forgetting that modifier semantics differ between languages.
- Exposing helpers publicly just to make testing easier instead of testing through behavior.
- Treating access modifiers as style choices instead of design decisions.
Summary
- '
publicexposes a member to outside callers.' - '
privatekeeps a member inside the class only.' - '
protectedusually allows access from subclasses, with language-specific details.' - Start with the most restrictive modifier and widen only when needed.
- Good access control improves encapsulation, maintainability, and API stability.

