devnotes.

Getters, Setters, and Controlled Access

When external code needs to read or write a private property, it does so through getter and setter methods — public methods dedicated to accessing a single property in a controlled way.

class Person {
    private age

    function getAge() {
        return this.age
    }

    function setAge(value) {
        if value < 0 or value > 150:
            throw Error("Age must be realistic")
        this.age = value
    }
}

p = new Person()
p.setAge(30)   // goes through validation
print(p.getAge()) // 30
p.setAge(-5)   // throws an error — invalid state is prevented

Compare this to making age public directly — any code anywhere could set person.age = -5 with no validation at all. Getters and setters turn a simple property assignment into an enforceable rule.

Not every property needs both. Some are read-only from the outside (only a getter — e.g. a computed fullName derived from firstName and lastName), and some might be write-only in rare cases (only a setter — e.g. a password, which should never be readable back out in plain form).

A caveat worth knowing: writing a getter and setter for every single property, with no actual logic inside them, doesn't add real encapsulation — it's just extra boilerplate around a public property. True encapsulation value comes from the validation, computation, or side effects a setter or getter can add. Modern languages increasingly offer shortcuts for the trivial case (like PHP's property hooks, C#'s auto-properties, or Python's @property decorator) while still allowing full custom logic when it's actually needed.

Getters and Setters in OOP | DevNotes