← Skill tree CS Skill Tree 0 CSCD210

Composition: a Class That Has Another Class

Textbook: BJP (Reges and Stepp)

Where you are: Week 0 review > Composition

Try This First

A Book needs an author with a first and last name. Decide whether to store the author as a separate Author object or as two loose String fields on Book, before reading on.

Reveal

Store an Author object. The author is its own thing with its own fields and behavior, so a Book should hold an Author (a “has-a” relationship). Book then delegates author work to the Author.

Before You Start

Check each box you can do from memory. A box you cannot check yet is not a problem; it points you to a quick refresher, not a grade.

See equals and hashCode for a full review of the prerequisite ideas.

Not sure? Take the 60-second self-check.

Try each from memory, then read the answer under it.

  1. Why does a class override equals? To compare objects by their contents instead of by their arrows.
  2. What rule ties hashCode to equals? Equal objects must return the same hashCode.

What You Need To Walk In With

Walk into the next class able to state these:

You should be able to: write a class that holds another class as a field and delegates to it at each of those sites.

How It Works

public final class Book implements Comparable<Book> {
    private final String title;
    private final Author author;   // the composed field, a class you wrote

    public Book(String title, Author author) {
        if (title == null || title.isBlank()) { throw new IllegalArgumentException("bad title"); }
        if (author == null) { throw new IllegalArgumentException("author required"); }
        this.title = title;
        this.author = author;       // stored, not recreated
    }

    @Override
    public String toString() {
        return "Book[title=" + title + ", author=" + author + "]";  // calls Author.toString
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Book other)) { return false; }
        return Objects.equals(title, other.title)
            && Objects.equals(author, other.author);                // calls Author.equals
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author);                         // uses Author.hashCode
    }

    @Override
    public int compareTo(Book other) {
        int byAuthor = author.getLastName().compareTo(other.author.getLastName());
        if (byAuthor != 0) { return byAuthor; }
        return title.compareTo(other.title);
    }

    public Author getAuthor() { return author; }
}

The composed author appears at five sites: the constructor stores it, toString prints it, equals compares it, hashCode includes it, and compareTo reaches into it. Each one delegates to the Author, so Book never re-implements author logic. This five-site shape is the recurring shape of composition.

Worked Example: Predict, Then Check

Author a = new Author("Ada", "Lovelace");
Book b1 = new Book("Notes", a);
Book b2 = new Book("Notes", new Author("Ada", "Lovelace"));
System.out.println(b1.equals(b2));

Assuming Author overrides equals on its fields, predict the output.

Reveal

true. Book.equals compares the titles (equal) and delegates the author comparison to Author.equals, which finds the two authors equal by their fields. Delegation makes Book equality follow from its parts.

A Common Mistake

Re-implementing the part’s logic inside the whole, or skipping a delegation site, breaks composition. For example, comparing authors by re-reading their name strings in Book.equals instead of calling Author.equals duplicates logic and drifts out of sync. Store the object and delegate to it at every site. (Source: BJP (Reges and Stepp), Ch 8.)

Go Deeper (optional)

For the curious: building a whole from parts and wiring one behavior through another is the same shape as composing functions in mathematics, f(g(x)): the result of the inner part feeds the outer. A Book.equals that calls Author.equals is exactly that composition of behaviors, which is why the math tree links here through function-composition.

Check Yourself

Close the notes and answer each one from memory, then reveal it. Pulling an idea back from memory is one of the strongest ways to make it stick.

Check your understanding

What is composition?

Tier 1 · BJP (Reges and Stepp), Ch 8

When a Book composes an Author, where does the author field appear?

Tier 2 · BJP (Reges and Stepp), Ch 8

How should Book.equals compare the author?

Tier 2 · BJP (Reges and Stepp), Ch 8

Book b1 and b2 have equal titles and equal-by-fields authors. With proper overrides, b1.equals(b2) is?

Tier 1 · BJP (Reges and Stepp), Ch 8