Encapsulation: Keep State Valid
Prevent an invalid mark from entering a record
A science mark must be finite and between zero and fifty. If any caller can overwrite it with arbitrary text or 99, every report needs to repair the damage later.
Encapsulation keeps internal state behind a supported interface. Updates pass through operations that preserve the object’s rules instead of exposing unrestricted writes.
State a rule
Describe the valid mark range and type.
Enforce an update
Reject unsuitable values without damaging the earlier mark.
Explain privacy
Distinguish a language boundary from security or secret storage.
Validate before changing the stored mark
Current state
The record holds a valid mark.
35Invalid request
99 is outside the allowed range; preserve state.
still 35Valid request
40 passes the checks.
now 40
An interface makes valid changes explicit
A private JavaScript field begins with # and must be declared in the class. Callers use methods rather than accessing that private field directly.
Privacy alone does not enforce the school rule. The method checks the requested value before storing it and reports whether the update succeeded. This prevents a rejected update from partly changing the record.
Before starting, review instances and methods. These examples use JavaScript; other languages can use different syntax and rules.
Reject an invalid update and accept a valid one
The first set call rejects 99 and returns false. read confirms the initial value is still 35. The next set accepts 40 and returns true.
Number.isFinite rejects nonnumeric values, NaN and Infinity. The range check then enforces the school-specific maximum.
JavaScript · local teaching example
class ScienceMark {
#value = 35;
set(value) {
if (!Number.isFinite(value) || value < 0 || value > 50) return false;
this.#value = value;
return true;
}
read() { return this.#value; }
}
const mark = new ScienceMark();
console.log(mark.set(99));
console.log(mark.read());
console.log(mark.set(40));
console.log(mark.read());Expected output
false
35
true
40Return a value rather than expose an editable container
This getter returns a numeric primitive, so changing the caller’s local variable does not change the private field.
A getter returning a mutable internal array or record would require more care: callers could mutate shared objects. Encapsulation is about the full interface, including results.
JavaScript · local teaching example
class Mark {
#value = 35;
read() { return this.#value; }
}
const mark = new Mark();
let local = mark.read();
local = 40;
console.log(mark.read());
console.log(local);Expected output
35
40Apply the rule to a small change
Use the same rules to accept a genuine zero mark and reject the string “40.”
Worked answer
Numeric zero satisfies the range. The quoted value is a string, so Number.isFinite rejects it before assignment. Conversion, if desired, should happen at a documented input boundary.
JavaScript · local teaching example
class ScienceMark {
#value = 35;
set(value) {
if (!Number.isFinite(value) || value < 0 || value > 50) return false;
this.#value = value; return true;
}
read() { return this.#value; }
}
const mark = new ScienceMark();
console.log(mark.set(0));
console.log(mark.set('40'));
console.log(mark.read());Expected output
true
false
0Recognize mistakes and limits
Private fields protect access under JavaScript’s language rules, not secrets from someone who controls the running environment. Server authorization and secure storage are separate concerns.
Define constructor validation too if initial state comes from external inputs. Avoid silent rejection that leaves callers thinking an update succeeded; a boolean or a meaningful error makes the outcome reviewable.
For the language or tool rules used here, see JavaScript class behavior.
Check the core idea
JavaScript · code for this question
class ScienceMark {
#value = 35;
set(value) {
if (!Number.isFinite(value) || value < 0 || value > 50) return false;
this.#value = value;
return true;
}
read() { return this.#value; }
}
const mark = new ScienceMark();
console.log(mark.set(99));
console.log(mark.read());
console.log(mark.set(40));
console.log(mark.read());Apply the idea to a new situation
Preserve rules at the state-changing boundary
Encapsulation provides operations that keep state valid. Validate before updating, report rejected requests and examine whether returned objects expose mutable internals.
Connect this idea with supported interfaces and meaningful validation errors.
Reaching the recap and completing the quizzes are separate milestones.