A half-finished form#
Think of a job application form. The company has printed most of it already: name, address, the signature line. But one box says “Describe why you want this job” and it is blank. The form is useless until each applicant fills that box in, and nobody would hand in the blank master copy as their application.
An abstract class is that form. Most of the class is written, but some methods are left blank on purpose, and every subclass must fill them in. Those blank methods are abstract methods: a heading with no body, ending in a semicolon. And just as nobody submits the blank master, Java will not let you create an object of an abstract class.
Abstract methods and abstract classes#
abstract class Shape {
private String name;
public Shape(String name) {
this.name = name;
}
public abstract double area();
public String describe() {
return name + " with area " + area();
}
}
class Circle extends Shape {
private double r;
public Circle(double r) {
super("circle");
this.r = r;
}
@Override
public double area() {
return Math.round(Math.PI * r * r * 100) / 100.0;
}
}
class Rect extends Shape {
private double w, h;
public Rect(double w, double h) {
super("rectangle");
this.w = w;
this.h = h;
}
@Override
public double area() {
return w * h;
}
}
public class Shapes {
public static void main(String[] args) {
Shape[] shapes = { new Circle(2), new Rect(3, 4) };
for (Shape s : shapes) {
System.out.println(s.describe());
}
}
}
circle with area 12.57
rectangle with area 12.0
Three things to notice:
area()inShapehas no body, just a semicolon, and is markedabstract. Any class holding an abstract method must itself be markedabstract.describe()is an ordinary, finished method in the same abstract class. It even callsarea(), trusting that every real shape will supply one. An abstract class can also have fields and constructors, andShapeuses its constructor to store the name.- The array is declared as
Shape[], and polymorphism does the rest: each object runs its ownarea().
Try to create the blank master copy and the compiler stops you:
abstract class Shape {
public abstract double area();
}
public class NoNew {
public static void main(String[] args) {
Shape s = new Shape();
}
}
NoNew.java:7: error: Shape is abstract; cannot be instantiated
Shape s = new Shape();
^
1 error
And a subclass that forgets to fill in the blank gets a precise complaint. The message tells you exactly which method is missing:
abstract class Shape {
public abstract double area();
}
class Triangle extends Shape {
private double base, height;
}
public class Forgot {
public static void main(String[] args) {
System.out.println("never gets here");
}
}
Forgot.java:5: error: Triangle is not abstract and does not override abstract method area() in Shape
class Triangle extends Shape {
^
1 error
The only ways out are to write the missing area(), or to mark Triangle abstract too, which passes the job further down the family.
When to make a class abstract#
Make a class abstract when both of these are true:
- It names a category, not a real thing. You can draw a circle or a square, but you cannot draw “a shape” that is no particular shape. Likewise “an employee” who is no particular kind of employee, or “an account” that is no particular kind of account.
- Every subclass must provide some behaviour, but each does it differently. Every shape has an area; each computes it its own way.
If the parent can give a sensible default for the method, it does not need to be abstract: write the default and let subclasses override it. Use abstract when there is no honest default, and forgetting to override would be a bug.
Interfaces: a promise any class can make#
Phones, headphones and electric toothbrushes have nothing else in common, but they can all promise to fit a USB-C charger. That promise is a standard. Any device can meet it, whatever family the device belongs to.
An interface is that standard in Java: a named list of method headings. A class signs up with the keyword implements, and must then write every method on the list.
interface Chargeable {
int batteryLevel();
void charge(int minutes);
}
class Device {
private String model;
public Device(String model) {
this.model = model;
}
public String getModel() {
return model;
}
}
class Phone extends Device implements Chargeable {
private int battery = 20;
public Phone(String model) {
super(model);
}
public int batteryLevel() {
return battery;
}
public void charge(int minutes) {
battery = Math.min(100, battery + minutes);
}
}
class Toothbrush implements Chargeable {
private int battery = 50;
public int batteryLevel() {
return battery;
}
public void charge(int minutes) {
battery = Math.min(100, battery + minutes / 2);
}
}
public class Iface {
public static void main(String[] args) {
Phone p = new Phone("Pixel");
Chargeable[] plugs = { p, new Toothbrush() };
for (Chargeable c : plugs) {
c.charge(60);
System.out.println(c.batteryLevel() + "%");
}
System.out.println(p.getModel() + " is at " + p.batteryLevel() + "%");
}
}
80%
80%
Pixel is at 80%
The rules that make interfaces different from classes:
- Methods in an interface are automatically
publicandabstract; you do not write those words. (Since Java 8 an interface may also containdefaultandstaticmethods with a body, and since Java 9privatehelper methods, but the heart of an interface is the list of promises.) - Any field in an interface is automatically
public static final: a shared constant, not per-object data. - You cannot create an object of an interface, but you can use it as a variable or array type, as
Chargeable[]does above. That is polymorphism again. - A class extends one class but can implement many interfaces, separated by commas.
PhoneextendsDeviceand is alsoChargeable.
Implementing class methods must be public. Leave the word off and you get the same “weaker access privileges” error as in the Object guide.
A real interface you will use: Comparable#
The Java library is full of interfaces. The one your course meets first is Comparable, which promises one method, compareTo. It follows the same rule as String’s compareTo: negative means “I come first”, zero means equal, positive means “I come after”. Keep that promise and Arrays.sort can sort your objects:
import java.util.Arrays;
class Student implements Comparable<Student> {
private String name;
private double gpa;
public Student(String name, double gpa) {
this.name = name;
this.gpa = gpa;
}
public int compareTo(Student other) {
return Double.compare(other.gpa, gpa);
}
@Override
public String toString() {
return name + " " + gpa;
}
}
public class Sort {
public static void main(String[] args) {
Student[] cls = {
new Student("Ana", 3.2),
new Student("Ben", 3.9),
new Student("Cy", 3.5)
};
Arrays.sort(cls);
System.out.println(Arrays.toString(cls));
}
}
[Ben 3.9, Cy 3.5, Ana 3.2]
Double.compare(x, y) does the subtraction-style comparison for two double values. Passing other.gpa first flips the order, which is why the highest GPA comes out first; swap the arguments for lowest first. Arrays.sort was written years before Student existed. It works because it only relies on the promise: anything Comparable has a compareTo. The <Student> after the interface name is generics, covered later in this series; it says “comparable to other Students”.
Abstract class or interface?#
| Abstract class | Interface | |
|---|---|---|
| Keyword to use it | extends | implements |
| How many per class | one | as many as you like |
| Can you create an object of it? | no | no |
| Constructors | yes | no |
| Fields | any kind, including private per-object data | only public static final constants |
| Methods with bodies | yes, as many as you like | only default, static and private ones |
| Relationship it expresses | is a (a circle is a shape) | can do (a phone can be charged) |
When to use an interface: when unrelated classes need to share an ability, or when a class needs more than one role. Phones and toothbrushes share no parent but can both be Chargeable.
When to use an abstract class: when closely related classes share real code and data, such as a name field, a constructor or a finished describe() method, and you only want to leave a few methods blank.
A quick exam test: if the sentence is “X is a kind of Y”, Y is probably a class (abstract if Y is only a category). If the sentence is “X can do Z”, Z is probably an interface, and its name often ends in -able.
Drawing them in UML#
UML marks abstract things in italics. Because italics are hard to write by hand, you may also see {abstract} after the name. An interface gets the label «interface» above its name. The arrows:
- extends (class to class): solid line, hollow triangle at the parent.
- implements (class to interface): dashed line, hollow triangle at the interface.
+------------------------------+ +------------------------------+
| Shape {abstract} | | «interface» |
+------------------------------+ | Chargeable |
| - name : String | +------------------------------+
+------------------------------+ | + batteryLevel() : int |
| + area() : double {abstract} | | + charge(minutes : int) |
| + describe() : String | +------------------------------+
+------------------------------+
^ ^
| :
| solid line : dashed line
+------------------------------+ +------------------------------+
| Circle | | Phone |
+------------------------------+ +------------------------------+
| - radius : double | | - battery : int |
+------------------------------+ +------------------------------+
| + area() : double | | + batteryLevel() : int |
+------------------------------+ | + charge(minutes : int) |
+------------------------------+
Notice Circle lists area() in plain type: it is the finished version. The abstract heading appears only in the parent.
An abstract class is a half-finished parent you extend (one only, is-a); an interface is a list of promises you implement (as many as you like, can-do). You can create an object of neither, and every abstract method must be written by the first non-abstract class below it.
Where these go wrong#
- Giving an abstract method a body, or a normal method no body. Abstract methods end in a semicolon; every other method needs braces.
- Writing
new Shape()for an abstract class ornew Chargeable()for an interface. Neither can be instantiated. Create a concrete subclass or implementing class instead. - Forgetting one abstract method in a subclass. The class must be marked abstract or the compiler names the missing method.
- Leaving
publicoff an implemented interface method. Interface methods are public, and an implementation cannot be weaker. - Writing
extendsfor an interface orimplementsfor a class. Classes are extended; interfaces are implemented. (One interface can extend another interface.) - Expecting per-object fields in an interface. Every interface field is a
public static finalconstant. - Mixing up the UML arrows. Solid line for extends, dashed line for implements, both with a hollow triangle at the general end.
Practice#
Answer each one on paper before you look at the solutions. Every answer that involves running code was checked by compiling and running it.
- Which of these lines compile, given
abstract class Animalandclass Cow extends Animal(which writes every abstract method)?Animal a = new Animal();Animal b = new Cow();Animal[] herd = new Animal[10]; Animaldeclarespublic abstract String sound();and a finishedspeak()that returns"The animal says " + sound(). Write the smallestCowclass that compiles, and say whatnew Cow().speak()returns.- A class
Robotalready extendsMachine. It also needs to beRechargeableandProgrammable. Should those two be abstract classes or interfaces? Why? - Write an interface
Playablewith one methodString play(), two classes that implement it, and a loop over aPlayable[]that callsplay()on each. - Give three differences between an abstract class and an interface.
- In UML, how do you tell an abstract class from an ordinary class, and how do you draw “
PhoneimplementsChargeable”?
Solutions#
- The second and third. You cannot create an
Animalobject (Animal is abstract; cannot be instantiated), but you can declareAnimalvariables and arrays, which is the whole point.new Animal[10]creates an array of ten empty slots, not ten animals, so it is allowed. Cowonly has to fill in the blank; it inheritsspeak():abstract class Animal { public abstract String sound(); public String speak() { return "The animal says " + sound(); } } class Cow extends Animal { @Override public String sound() { return "moo"; } } public class QFix { public static void main(String[] args) { Animal a = new Cow(); System.out.println(a.speak()); } }The animal says moo- Interfaces. A class can extend only one class, and
Robothas used its one onMachine. It can implement any number of interfaces:class Robot extends Machine implements Rechargeable, Programmable. They also describe abilities (can-do), which is what interfaces are for. - The array type is the interface, and each object runs its own
play():interface Playable { String play(); } class Song implements Playable { public String play() { return "playing a song"; } } class Podcast implements Playable { public String play() { return "playing a podcast"; } } public class QPlay { public static void main(String[] args) { Playable[] queue = { new Song(), new Podcast() }; for (Playable p : queue) { System.out.println(p.play()); } } }playing a song playing a podcast - Any three of: a class extends one abstract class but can implement many interfaces; an abstract class can have constructors and an interface cannot; an abstract class can have ordinary per-object fields, while interface fields are all
public static finalconstants; an abstract class can have any number of finished methods, while an interface allows bodies only ondefault,staticandprivatemethods; abstract classes express is-a, interfaces express can-do. - The abstract class name (and any abstract method) is written in italics, or marked
{abstract}. “Implements” is a dashed line fromPhonetoChargeablewith a hollow triangle atChargeable, andChargeable’s box is labelled«interface».
Test-readiness checklist#
These are the items from the course’s Exam 2 topic list that this guide covers. Tick each one only when you can do it without looking.
- ☐ I can write an abstract class with abstract methods and explain why it cannot be instantiated.
- ☐ I can say when to make a class abstract.
- ☐ I can write and implement an interface, and explain when to use an interface instead of an abstract class.
- ☐ I can draw the UML for abstract classes and methods and for interfaces, with the right arrow for each.
Test yourself in the free Kestrel Exams app
40 practice questions on abstract classes, interfaces and default methods, with every code answer checked by compiling and running it. Free, offline, no account.
Practise abstract classes and interfaces →Frequently asked questions#
What is an abstract class in Java?
A class marked abstract that cannot be instantiated. It can contain fields, constructors and finished methods like any class, plus abstract methods: headings with no body that every concrete subclass must override. It is used for a general category whose subclasses share code but each supply some behaviour differently.
What is an abstract method?
A method declared with the abstract keyword and no body, ending in a semicolon, such as public abstract double area();. Any class containing one must be abstract, and the first non-abstract subclass must override it or the code does not compile.
What is an interface in Java?
A named set of method headings that a class promises to provide by writing implements. Interface methods are public and abstract unless they have a body (default and static methods, and since Java 9 private helper methods), and interface fields are public static final constants. A class can implement many interfaces, and an interface can be used as a variable type.
What is the difference between an abstract class and an interface?
A class can extend only one abstract class but implement many interfaces. Abstract classes can have constructors, ordinary fields and any number of finished methods; interfaces have no constructors, only constant fields, and bodies only on default, static or private methods. Abstract classes model is-a relationships among closely related classes; interfaces model abilities that unrelated classes can share.
When should I use an interface instead of an abstract class?
Use an interface when unrelated classes need to share an ability, or when a class needs more than one role, because Java allows only one superclass. Use an abstract class when closely related classes share real code or data and only a few methods differ.
How are abstract classes and interfaces shown in UML?
Abstract classes and abstract methods are written in italics or marked {abstract}. Interfaces are labelled with the stereotype <<interface>>. Inheritance from a class is a solid line with a hollow triangle at the parent; implementing an interface is a dashed line with a hollow triangle at the interface.
Something here not clear? A topic you wish we covered? Tell us. We read every message, and a request is the fastest way to get a guide written — several of these exist because somebody asked.