devnotes.

Public, Private, and Protected

Access modifiers (also called visibility modifiers) control which parts of a program can access a class's properties and methods. Most mainstream OOP languages provide three core levels:

  • public — accessible from anywhere: inside the class, from subclasses, and from external code. This is the class's public API.
  • protected — accessible from within the class itself and from any subclass, but not from unrelated external code.
  • private — accessible only from within the exact class where it's declared; not even subclasses can access it directly.
class Employee {
    public name           // anyone can read/write this
    protected salary       // only Employee and its subclasses
    private ssn             // only Employee itself

    private function calculateTax() { ... } // internal helper, not part of the public API

    public function getAnnualSalary() {
        return this.salary * 12 // public method can use the protected property internally
    }
}

class Manager extends Employee {
    function giveBonus(amount) {
        this.salary += amount // OK — protected is accessible from a subclass
        // this.ssn — ERROR, private is not accessible even from a subclass
    }
}

emp = new Employee()
emp.name = "Alice"    // OK — public
// emp.salary = 50000  // ERROR — protected, not accessible from outside
// emp.ssn = "123-45"  // ERROR — private, not accessible from outside

The general guideline: default to the most restrictive visibility that still gets the job done. Start with private, and only widen to protected or public when there's a genuine need for subclasses or external code to access something directly. This keeps the class's true public contract small, intentional, and easy to reason about — every public member is a promise to the rest of the codebase that must be kept even as internals change.

Access Modifiers in OOP: public, private, protected | DevNotes