Designing Classes, COMP SCI Ch. 8 – Study Notes
offline

Difficulty: Intermediate | Prerequisites: Arrays and ArrayLists (Unit 7), basic class and method syntax


Big Picture

Knowing how to write a class that compiles is one thing. Knowing how to design a class well is another. Chapter 8 is about the principles that separate clean, maintainable code from a tangled mess: cohesion, coupling, accessor vs. mutator separation, scope, preconditions, and static members. These ideas show up in every professional codebase and are the kind of thing exam questions love to test conceptually, not just syntactically.


TL;DR

A well-designed class represents a single concept (cohesion), depends on as few other classes as possible (low coupling), and separates methods that read state (accessors) from methods that change it (mutators). Understanding variable scope, the this keyword, preconditions/postconditions, and static members rounds out the toolkit for writing classes that are correct, readable, and easy to maintain.


Key Terms

Cohesion

The principle that a class should represent a single concept, with every field and method relating directly to that concept. Think of it as "does everything in this class belong under its name?"

Coupling (dependency)

A measure of how much one class relies on another. Class A depends on Class B if any method in A uses B. Lower coupling means easier maintenance; changing one class won't ripple through the whole program.

UML (Unified Modeling Language)

A standard notation for visualising object-oriented designs. Class diagrams in UML show classes, their fields, their methods, and the relationships between them.

Accessor method

A method that returns information about an object's state without changing it. In simple terms, it reads but does not write.

Mutator method

A method that modifies an object's state. Any method with a side effect on the object's data is a mutator.

Immutable class

A class with no mutator methods. Once an object is created, its state never changes. String is the classic Java example.

Side effect

Any externally observable data modification caused by a method. Mutator methods have side effects by definition.

Call by value

Java's parameter-passing mechanism. When you call a method, the argument's value is copied into the parameter variable. Changes to the parameter inside the method do not affect the original variable outside it.

Precondition

A requirement that the caller of a method must satisfy before the call. Preconditions protect methods from receiving bad input.

Postcondition

A condition guaranteed to be true after a method completes, provided the precondition was met. Two flavours: the return value is computed correctly, or the object is left in a specific state.

Static variable (class variable)

A variable that belongs to the class itself rather than to any individual object. All instances share one copy.

Static method

A method that belongs to the class rather than an instance. It cannot access instance variables or use this.

Scope

The region of a program in which a variable can be accessed. A local variable's scope runs from its declaration to the end of the enclosing block.

this keyword

A reference to the current object. Used to distinguish an instance variable from a local variable when they share the same name: this.value refers to the instance field.

Package

A set of related classes grouped under a common namespace. java.lang is always imported automatically. Other packages require an explicit import statement, or you can use the fully qualified name (e.g. java.util.Scanner).


Core Content

Identifying Classes

  • Look for nouns in the problem description. Nouns tend to become classes.

  • A rectangle, for instance, is defined by four points whose connecting lines are parallel in pairs and perpendicular where they intersect.

Cohesion

  • Every field and method should relate to the single concept the class represents.

  • If a class starts doing two unrelated jobs, it has lost cohesion and should probably be split.

Coupling and Dependencies

  • A class depends on another if its methods reference that class in any way.

    • Example: CashRegister depends on Coin, but Coin does not depend on CashRegister because none of Coin's methods reference CashRegister.

  • Minimising dependencies pays off when you need to modify or replace a class later.

Accessors, Mutators, and Immutability

  • Keep accessors and mutators separate. A method should either ask a question or change state, not both (where possible).

  • Immutable classes (like String) have no mutators. Their objects can be safely shared across the program without worrying about unexpected changes.

  • Side effects are any observable modification of data. Mutators have them; accessors should not.

Call by Value

  • Java copies the argument's value into the method parameter.

  • Inside the method, the parameter is a local copy. Reassigning it does not change the caller's variable.

Preconditions and Postconditions

  • A precondition states what must be true before a method runs (e.g. "balance must be non-negative").

  • A postcondition states what will be true after the method completes, assuming the precondition was met.

  • If the precondition is violated, the method's behaviour is undefined.

Static Variables and Methods

  • A static variable is shared across all instances: one copy per class, not per object.

  • A static method can be called on the class itself (Math.sqrt(4)) and cannot access instance fields.

Variable Scope

  • A local variable's scope extends from its declaration to the end of the block that encloses it.

  • Two local variables cannot share the same name within overlapping scopes.

  • A local variable can have the same name as an instance variable. Inside the method, the local variable takes priority. Use this.variableName to access the instance field.

Scope example that compiles:

public void method1(int x) {
    double x = 25.6;
}

The parameter x is an int and the local x is a double, so Java treats them as having different definitions.

Scope example that does not compile:

public void method1(int x) {
    int y = 0;
    double x = 25.6;
    if (x > 10) {
        y = 2;
    } else if (x < 0) {
        int y = 7;  // redeclaration of y in overlapping scope
    }
}

The second int y = 7 attempts to redeclare y within its enclosing scope, which is not allowed.

Packages

  • A package is a set of related classes.

  • java.lang is imported automatically in every Java program.

  • To use a class from another package, either import it (import java.util.ArrayList;) or use its fully qualified name (java.util.Scanner in = new java.util.Scanner(System.in);).

  • Wildcard imports pull in everything from a package: import java.util.*;

  • Package access (default, no modifier) allows all classes within the same package to access the member. It is almost as open as public, but invisible to classes outside the package.


Real-World Applications

Cohesion and coupling are not academic abstractions. In professional codebases, low coupling means one team can refactor their module without breaking another team's code. Immutability is central to thread-safe programming: if an object never changes, multiple threads can read it at the same time without locks.


Common Misconceptions

  • Students often confuse cohesion and coupling. Cohesion is about a single class doing one job well. Coupling is about how much one class relies on others. High cohesion is good; high coupling is bad.

  • Students sometimes think Java passes objects "by reference." Java always passes by value. For objects, the value being passed is the reference (the memory address), so the method can modify the object's fields but cannot make the caller's variable point to a different object.

  • Students assume that if a class has dependencies, it is poorly designed. Some coupling is unavoidable; the goal is to minimise unnecessary dependencies.

  • Students forget that two local variables in overlapping scopes cannot have the same name, even if they have different types.


Why It Matters / Exam Flags

⚠️ Know the definitions of cohesion, coupling, accessor, and mutator. These appear as short-answer or multiple-choice questions frequently.

⚠️ Be able to identify whether a given method is an accessor or a mutator.

⚠️ Understand preconditions and postconditions, and what happens if a precondition is violated (behaviour is undefined).

⚠️ Expect scope-related questions: can a local variable shadow an instance variable? (Yes, use this to reach the instance field.) Can two locals share a name in the same block? (No.)

⚠️ Static vs. instance: know that a static method cannot use this or access instance variables.


Quick Self-Test

True or False: An immutable class has no accessor methods.

False. An immutable class has no mutator methods. It can (and usually does) have accessors.

Fill in the blank: When a local variable and an instance variable share the same name, use _______ to refer to the instance variable.

this

True or False: Java uses call by reference for objects.

False. Java always uses call by value. For objects, the value passed is a copy of the reference.

Fill in the blank: A _______ variable belongs to the class itself, not to any individual object.

static


Practice Q&A

Q: Why is the CashRegister class from Chapter 4 considered not cohesive?

A: It has responsibilities and dependencies that go beyond a single concept, making it do more than one job.

Q: Why does the Coin class not depend on the CashRegister class?

A: None of Coin's methods reference or use CashRegister in any way.

Q: What is the difference between a precondition and a postcondition?

A: A precondition is what must be true before a method is called. A postcondition is what is guaranteed to be true after the method finishes (assuming the precondition was met).

Q: Can a static method access instance variables directly? Why or why not?

A: No. A static method belongs to the class, not to any particular object, so there is no instance whose fields it could access.

Q: What is package access, and when does it apply?

A: Package access is the default access level when no modifier (public, private, protected) is specified. Members with package access can be used by any class in the same package but are invisible outside it.


Connections to Other Topics

These design principles carry directly into Chapter 9 (Inheritance) and Chapter 10 (Interfaces), where cohesion and coupling guide decisions about when to extend a class vs. implement an interface. Preconditions and postconditions become more important as class hierarchies grow and overridden methods must honour the contracts of their superclass.


Related Terms / Search Tags

class design, cohesion, coupling, dependency, UML, Unified Modeling Language, accessor, mutator, immutable, immutability, String immutable, side effect, call by value, pass by value, precondition, postcondition, static variable, static method, class variable, scope, local variable scope, variable shadowing, this keyword, package, java.lang, import, wildcard import, access modifier, package access, COMP SCI, Texas A&M, intro to programming, Chapter 8