CSCD 211 › lessons

Prerequisite: the class, built from "what stops an object from being wrong?"

This is the rung between references and equality. In CSCD 210 you wrote a class with fields and a constructor. This lesson shows you the one habit that turns a class from a bag of data into something 211 can build on: a constructor that refuses to make an invalid object, so a wrong Course never exists in the first place. The climb is short and every rung is a click.

Quick check before you climb (retrieval first)

Answer from memory before reading. No stakes; retrieving 210 is what makes the new idea land.

Check yourself. In 210 you made fields private and reached them through methods instead of touching them directly. In one sentence, what does making a field private stop other code from doing?

The point

By the end you can say what a class is (state plus the rules that guard it), you can write a constructor that validates before it assigns so an invalid object cannot be built, and you can name the property a good constructor protects, an invariant, which is the floor every later 211 idea stands on.

The problem (sit with this before reading on)

A Course has a credit count, and a real course has between one and six credits. Nothing about an int field knows that:

Course c = new Course("CSCD 211", "Programming Principles II", -5);

If the constructor just copies the number in, this builds a course with minus five credits. It compiles, it runs, and the broken value travels through every total, every sort, and every report until something far away fails on it. The mistake was allowed at the only moment it was cheap to stop.

Check yourself. The constructor copied -5 straight into the field. In one sentence, why is catching this at construction better than catching it later when a total looks wrong?

Atom 1: a class is state plus the rules that guard it

A class is two things at once: the state, its fields, and the rules about what counts as a valid object. In 210 it was easy to see only the first. The second is what makes a class trustworthy. The fields say what a Course holds; the rules say a Course always has a non-blank code and a credit count between one and six. A class that states its rules and enforces them is one you can build on without re-checking it everywhere.

Check yourself. Name the two parts of the Course class in this lesson: the state, and the rule that should always hold.

Atom 2: encapsulation is how the rule is enforced

For the rule to mean anything, no one can be allowed to set a field around it. That is what private is for. If credits were public, any code could write c.credits = -5 and the rule would be a suggestion. Private fields plus a constructor and methods that are the only way in make the class the single gatekeeper of its own state. Encapsulation is not about hiding for its own sake; it is about being the one place the rule is checked.

Check yourself. In one sentence, why does the validity rule only hold if the fields are private?

Atom 3: the click, a validating constructor means a wrong object never exists

Here is the habit 211 holds you to on every line. The constructor checks each precondition first, and assigns a field only after every check has passed. If a check fails, it throws, and no object is returned at all:

public Course(String courseCode, int credits) {
    if (courseCode == null || courseCode.isBlank()) {
        throw new IllegalArgumentException("courseCode must not be blank");
    }
    if (credits < 1 || credits > 6) {
        throw new IllegalArgumentException("credits must be 1 to 6");
    }
    this.courseCode = courseCode;
    this.credits = credits;
}

The payoff is sharp: there is no such thing as a half-built or invalid Course. Either you get a valid object or you get an exception, never a broken object that compiles. The property that every Course that exists is valid is called an invariant, a statement that is true for the whole life of every object of the class. The validating constructor is what establishes it, and because the fields are final and private, nothing can break it afterward.

Going deeper (optional). An invariant is the programming form of an idea you meet in math and logic: a property preserved by every operation. The constructor establishes it and immutability preserves it, so the property holds for the object's whole life. That is the same shape as a loop invariant or an inductive invariant, one claim that stays true through every step.

Collectible insight. A validating constructor means a half-built object never exists: you get a valid object or an exception, never a broken one. The always-true property it protects is the class invariant.

Check yourself. Two calls: new Course("CSCD 211", 5) and new Course(" ", 5). In one sentence each, what does each return or do?

Atom 4: why Week 1 cannot reason without this

Week 1 orders and compares Course objects, and it does so trusting that every Course it touches is valid: the order can compare credits knowing they are one to six, equality can compare codes knowing they are non-blank. That trust is the invariant from Rung 3. Without a validating constructor, every method would have to re-check the data or risk acting on garbage, and the clean reasoning of Week 1 would collapse. This is why the given Course validates every field before it sets it, and why this prerequisite sits one rung below the first lecture: the order and the equality you are about to build both stand on objects that are guaranteed valid.

Check yourself (competency close). Finish in your own words: "A class is ___ plus . A validating constructor protects an invariant, which means , and Week 1 needs it because ___."

What you collected