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.