ReviseAlgo Logo

Object-Oriented Programming

Access Specifiers

public, private, and protected — controlling member visibility and encapsulation

Interview: Core encapsulation concept — every OOP interview discusses access control

Access Specifiers

Access specifiers control the visibility of class members — who can read or call them. They are the primary mechanism for encapsulation: hiding implementation details and exposing only the intended interface.

Specifier Same Class Derived Class External Code Use When
publicInterface — callable by all users
protectedInheritance hooks — only derived classes
privateImplementation details — default in class

Encapsulation and Invariants

Making member variables private is the foundation of encapsulation. Public setters can validate input and maintain class invariants (e.g., ensuring a counter is non-negative). Public getters can return derived values without exposing the raw storage. This allows changing the internal representation without breaking code that uses the class.

struct Default vs class Default

In struct, all members and inheritance is public by default. In class, all members and inheritance is private by default. Everything else — constructors, methods, templates — is identical. Convention: use struct for passive data aggregates, class for types with invariants.

Interview Corner

Q: Why should data members almost always be private?

A: Public data members break encapsulation — any code can modify them without the class knowing, making it impossible to maintain invariants. If a member is later changed (from int to float, or to a computed value), all code accessing it must change. Private members with public accessors allow the internal implementation to change without affecting users of the class.

Q: When should you use protected vs private?

A: Use protected for members that derived classes need to access directly — extension hooks, virtual helper methods that subclasses override. Keep implementation details private even from derived classes — this gives the base class freedom to change its internals without breaking derived classes. As a guideline: if a derived class needs a member, either make it protected or provide a protected accessor.

Common Pitfalls

  • Making everything public for convenience: Loses encapsulation — anyone can break invariants. Make members only as accessible as needed.
  • Overusing protected: Protected data members in a base class couple derived classes tightly to the implementation — prefer providing protected methods instead.

Best Practices

  • Default to private for all data members — expose only what is necessary through well-designed public methods.
  • Prefer protected methods over protected data — derived classes should call behavior, not manipulate raw state.