← Skill tree CS Skill Tree 0 CSCD211

An Interface Is a Promise a Type Makes

12 min read

Jump to a section

Here is a small sort that puts a Book array in order:

static void sortBooks(Book[] a) {
    for (int i = 0; i < a.length - 1; i++) {
        if (a[i].comesAfter(a[i + 1])) {
            swap(a, i, i + 1);
        }
    }
}

Now you have Course and you want the same sort. Copying the whole method and changing Book to Course feels wrong, and it is, because the sort never reads a title or a course code. It asks one question: which of these two comes first. So why does Java make you name a class at all, when the only thing the sort needs is that one capability? Answering that is what builds the interface, and by the end the word Comparable will not be a keyword to memorize. It will be the obvious name for a promise you already saw the need for.

Quick check before you climb (retrieval first)

Answer from memory before reading on. No stakes; pulling 210 back up now is what makes the new idea stick.

Check yourself. In 210 you wrote a method and then called it: book.getTitle(). The call works because the Book class has a method with that exact name and signature. Say, in one sentence, what the caller is relying on when it writes book.getTitle().

Check

the caller is relying on Book to have a method with that exact name and signature, so the promise that getTitle exists is what lets the call compile and run.

The essentials

If you only have a few minutes, walk away with this much and you are on solid ground.

Bare-minimum takeaways

What you can do after this lesson

By the end you can explain why a sort does not need to know an object’s class, only one capability it has; you can read implements Comparable as a type signing a named promise and supplying the method body; and you can say why one sort, written before your class existed, can order your objects the moment your type keeps that promise. The lesson reads implements Comparable as a type signing a promise it must keep, then splits the built-in order a type carries (Comparable) from the order you hand in from outside (Comparator).

The problem

Before you reach for copy-paste, look at what that Book sort actually touches:

for (int i = 0; i < a.length - 1; i++) {
    if (a[i].comesAfter(a[i + 1])) {
        swap(a, i, i + 1);
    }
}

The sort never reads a title, a price, a course code, or a credit count. The only thing it ever asks of a Book, or a Course, is one question: given these two, which one comes first. Everything else about the class is invisible to it.

Check yourself. The sort above only ever calls comesAfter on its elements. Without knowing the fix yet, name the one thing the sort actually needs from any type it is asked to sort.

Check

it needs only one capability, the ability to answer which of two elements comes first, and nothing else about the class.

Rung 1: the sort needs a capability, not a class

A sort that says Book[] in its signature can only ever sort books, even though it never uses anything that makes a book a book. That is the waste. The honest description of what the sort can handle is not a class at all. It is a capability: “anything that can tell me which of two of them comes first.” A Book has that capability. So does a Course. So does a Section you have not written yet. The class is the wrong unit to ask for, because the orders you want to sort share a capability, not a family.

So the question becomes mechanical: how do you write down a capability in Java, as a thing the sort can demand, without naming any one class that has it. Java has one construct built for exactly this, and it is the interface.

Code should ask for the smallest capability it needs, not the biggest class that happens to have it. A sort needs “can be compared,” never “is a Book.”

Check yourself. Two classes, Book and Course, are unrelated; neither is built from the other. They share no fields. Yet one sort should handle both. In one sentence, what do they have in common that the sort cares about?

Check

both can answer the same one question, which of two of them comes first, so they share a capability even though they share no fields and no parent class.

Rung 2: an interface is a named promise with no body

An interface is a name for a capability and the exact methods that capability requires. In its most common form it carries no working code, only the signatures a type must fill in. Modern Java lets an interface include a few ready-made methods, which you study later in CSCD 211; Comparable is the pure kind, just a single signature; Comparator also has one method you must write (compare), though it ships extra ready-made helpers you meet later. Here is the one Java already ships, simplified to its heart:

public interface Comparable<T> {
    int compareTo(T other);
}

Read it literally. It declares a type named Comparable. The <T> in angle brackets is a stand-in for whatever type fills it in, so Comparable<Course> reads as a promise to compare against other Course objects (you will study this generic angle-bracket syntax in more detail in CSCD 211). It promises one method, compareTo, that takes another object and returns an int. It supplies no body, because an interface does not say how any particular type compares; it only says that a type claiming this capability must provide that method. The interface is the promise; the class that signs it provides the proof.

A class signs the promise with implements, and then it must keep it by writing the method:

public class Course implements Comparable<Course> {
    private String courseCode;   // a code like "CSCD211", set in the constructor

    public int compareTo(Course other) {
        return this.courseCode.compareTo(other.courseCode);
    }
}

implements Comparable<Course> is Course declaring “I can answer which of two courses comes first.” The compiler now refuses to build Course unless that method is present, so the promise cannot be claimed and then quietly broken. The order you write inside is the one from the previous rung: a sign, never a subtraction. Here it delegates to String.compareTo, which already returns a sign. The interface decided the method must exist; you decided what the order is.

A common belief is that writing implements Comparable gives a class a working compareTo for free, the way extending a class hands you its methods. It is a fair guess, because a subclass inherits real, runnable code from its parent, so implements looks like the same move. It is not. A pure interface carries no body to inherit. It states the method that must exist and nothing else, so a class that writes implements Comparable and stops there does not compile. Building Java Programs makes the same point: an interface “specifies a set of methods” that an implementing class is obligated to provide, not a set of methods it receives (Reges and Stepp, chapter 9). The interface hands you the obligation, not the answer.

An interface is a named set of method signatures: a promise a type can sign with implements and must keep by supplying the bodies. A pure one like Comparable carries no state and no method bodies, only the signatures a type fills in.

Check yourself. A class writes implements Comparable<Course> but never declares a compareTo method. Predict what happens, and say which line is at fault.

Check

it does not compile; the implements clause obligates the class to provide compareTo, so the class header is at fault for claiming a promise the class does not keep.

Rung 3: write the code once, against the promise, and every keeper of the promise works

Here is the payoff, and it is the reason interfaces exist at all. A sort can name the interface in its signature instead of a class:

static void sort(Comparable[] items) {
    // ... only ever calls items[i].compareTo(items[j])
}

This method was written once. It can be compiled before Course exists. It accepts any array whose elements implement Comparable, and it orders them by calling the one method the promise guarantees. The day you write class Course implements Comparable<Course>, your courses become sortable by this exact code, with not one line of the sort changed. This is what Java’s real Collections.sort and Arrays.sort do, and it is why they can sort a type the library authors never heard of. The real library signature uses generics, like sort(Comparable<? super T>[]); we show the plain Comparable[] form here to keep the one idea, a sort that depends only on the promise, in front. The <? super T> part is a generics wildcard you will study later in CSCD 211, so you can ignore it here.

That is the whole bargain of an interface. The code that uses the capability and the code that provides the capability are written by different people at different times and never have to meet. They agree only on the promise: the method name, what goes in, what comes out. A new type joins the moment it keeps that promise, and nothing already written has to change to admit it. You will hear this called programming to an interface, and the property it buys, adding new types without reopening old code, is called open for extension and closed for modification, a design idea you will return to often.

Code written against an interface runs for every type that keeps the promise, including types written later. One sort, every comparable thing, no edit to the sort.

Check yourself. A library author ships sort(Comparable[] items) years before your class exists. Later you write a brand-new class that implements Comparable. In one sentence, why can that older sort order your new objects without being recompiled or changed?

Check

the sort depends only on the Comparable promise and never on the concrete class, so any type that keeps the promise fits its signature and the unchanged sort can call compareTo on it.

Rung 4: a type can keep many promises, and a promise can be handed in from outside

Two more facts and the picture is complete.

First, a class can sign more than one promise. In the EWU scheduling model a CourseSection can be Comparable (it has a natural order, by course code) and also Schedulable (it can report the time block it occupies) and Conflictable (it can answer whether it overlaps another section in time), because keeping several unrelated promises is normal and each is a separate small capability. This is different from a class being built from a parent class, which you study later in CSCD 211; an interface is a capability a type claims, not a family it belongs to.

Second, Comparable is the order a type carries built in, its one natural order. But often you want a different order for the same type, by title instead of by code, and you do not own the class to add an order to it, or you need several orders at once. For that, Java has a second interface, Comparator, that holds the order outside the type:

public interface Comparator<T> {
    int compare(T a, T b);
}

A Comparator is the same idea as Comparable, a one-method promise about ordering, with one difference: it is a separate object you hand to the sort from outside, rather than a method baked into the type. These two split on a clean seam. The built-in promise a Course carries is Comparable. The handed-in promise you supply from outside is Comparator. Both are interfaces; both are one method; you already know what that means.

Comparable is the one order a type carries inside itself; Comparator is an order handed in from outside. Both are one-method interfaces, so a type can be sortable by its own rule and by any number of outside rules at once.

Check yourself (competency close). Finish in your own words: “An interface is a named with no . A class signs it with and keeps it by . Code written against the interface works for , because it depends only on the .”

Check

an interface is a named promise with no body; a class signs it with implements and keeps it by supplying the method bodies; code written against it works for every type that keeps the promise, because it depends only on the promise and not the concrete class.

Check Yourself

Close the notes and answer from memory, then reveal the explanation. Pulling an idea back from memory, and choosing against a tempting wrong answer, is one of the strongest ways to make an idea stick and to catch a misconception before it reaches real code.

Check your understanding

Book and Course are unrelated: neither is built from the other and they share no fields. Yet one sort should order arrays of either. What do they have in common that the sort actually cares about?

A class writes implements Comparable<Course> but never declares a compareTo method. What happens, and which line is at fault?

A library author ships sort(Comparable[] items) years before your class exists. Later you write a brand-new class that implements Comparable. The older sort orders your new objects with no recompile and no change. Why is that possible?

Where to read more (use whichever fits you)

You do not need a book for this; the lesson stands on its own. If you learn better from a text, or want a free option, each resource covers interfaces from its own angle.

The five ideas to keep

With the interface in hand, implements Comparable reads as a type signing a promise you understand, and the split between the built-in order and the handed-in one is a seam you saw coming. The order itself, why it is a sign and never a subtraction, is the rung directly below this one in the order-is-a-sign prerequisite.