Chapter 4 · Robust, modern Java
Interfaces and polymorphism
Step 1 of 21 · Concept
Same question, different answers
A rectangle and a circle are different classes. A program that adds up areas only needs to ask each one the same question: what is your area?
In this lesson you will:
- write an interface that names such a question,
- answer it in several classes,
- loop over different objects as one list.
Step 2 of 21 · Concept
An interface names a question
The keyword interface starts one, where a class says class:
public interface Shape {
double area();
}
- An interface lists methods without bodies:
;where the body would be. - A class that implements it promises to write every one of them.
- The methods it lists are
public, so the class's method sayspublictoo.
Step 3 of 21 · Quiz
A broken promise
class Rectangle implements Shape has fields and a constructor, but no method area. What happens?
Step 4 of 21 · Demo
An interface and two classes
s has the type Shape. It holds a Rectangle first, then a Circle. Run it.
Step 5 of 21 · Trace
One variable, two objects
s is a box in main's frame. Press Next and watch where its arrow points.
public class Main {
public static void main(String[] args) {
Shape s = new Rectangle(3, 4);
System.out.printf("rectangle: %.2f%n", s.area());
s = new Circle(2);
System.out.printf("circle: %.2f%n", s.area());
}
}- Line 3 made a
Rectangleon the heap.sholds an arrow to it. s.area()ran theareaof theRectangle: 3 × 4 is 12.- Line 5 made a
Circle, andsnow points to it. Nothing points to theRectangle: the garbage collector will remove it. - The same call,
s.area(), ran theareaof theCirclethis time.
Step 6 of 21 · Concept
One call, many forms
The type of s says what you may ask: Shape has area(), so s.area() compiles.
The object at the end of the arrow decides which area() runs. The same line gives a different answer for each
class. This is polymorphism: one call, many forms.
Step 7 of 21 · Quiz
Which area runs?
Shape s = new Circle(1); Which method does s.area() run?
Step 8 of 21 · Exercise
Your turn: a square
Square.java holds an empty class. Make Square implement Shape, with a constructor Square(double side) and
an area() that returns the side times itself. The program must print:
square: 25.00
Rectangle in the step An interface and two classes has the same shape, with one field instead of two.
The header is public class Square implements Shape. Then a field side, the constructor, and
public double area().
public double area() {
return side * side;
}
Step 9 of 21 · Concept
A list of shapes
List<Shape> shapes = List.of(new Square(2),
new Circle(1), new Rectangle(4, 6));
Listis an interface, and lesson 13'sArrayListimplements it.- A
List<Shape>holds arrows to objects of every class that implementsShape. List.of(…)makes a list of the values you give it. It cannot change afterwards.- A for-each loop over it asks each object the same question.
Step 10 of 21 · Quiz
Predict the loop
Square, Circle and Rectangle implement Shape. Type exactly what this loop prints.
List<Shape> shapes = List.of(new Square(2),
new Circle(1), new Rectangle(4, 6));
for (Shape s : shapes) {
System.out.printf("%.2f%n", s.area());
}
Step 11 of 21 · Demo
See it run
Run it and compare with your answer. Shape, Square, Circle and Rectangle are hidden in this block.
Step 12 of 21 · Exercise
Your turn: the total area
Write the method totalArea: it returns the sum of the areas of every shape in the list. The program must print:
total: 37.00
That is 4 + 9 + 24. Shape, Rectangle and Square are hidden in this block.
Start a double total at 0, and add each shape's area to it in a loop.
for (Shape s : shapes), and inside it total += s.area();. Return total after the loop.
double total = 0;
for (Shape s : shapes) {
total += s.area();
}
return total;
Step 13 of 21 · Concept
Abstract classes share code
An abstract class sits between a class and an interface. It may have fields, a constructor and methods with
a body. Its abstract methods have none: every subclass, extends Vehicle, must write them.
public abstract class Vehicle {
private final String owner;
Vehicle(String owner) { this.owner = owner; }
String describe() {
return owner + " rides on " + wheels() + " wheels";
}
abstract int wheels();
}
| interface | abstract class | |
|---|---|---|
| fields in each object | no | yes |
| methods with a body | default ones | any |
objects made with new | no | no |
Step 14 of 21 · Demo
A bike and a car
Bike and Car write only wheels. They get owner and describe from Vehicle. Run it: describe calls the
wheels of the object it runs on.
Then add new Vehicle("Alan") to the list and run it again: javac refuses, since Vehicle is abstract.
Step 15 of 21 · Concept
Asking what an object is
Sometimes a loop needs to know which class an object really is.
s instanceof Circleistruewhenspoints to aCircle.s instanceof Circle calso gives you that object as a variablecof typeCircle.
With c you can call the methods that only Circle has.
Step 16 of 21 · Demo
instanceof
This Circle has one more method, radius(). Run it.
Step 17 of 21 · Quiz
What may you ask?
Shape s = new Circle(1); Does s.radius() compile?
Step 18 of 21 · Concept
Extend or implement?
| write | it says | how many |
|---|---|---|
extends | is a kind of, and shares the code of | one class |
implements | can do | many interfaces, with commas |
When the classes share no code, choose an interface.
Step 19 of 21 · Check yourself
Check yourself: animals
Write the interface Animal with the methods String name() and String sound(). Write the classes Dog and
Cat that implement it. A constructor takes the name; a dog says Woof, a cat says Meow.
Then complete main, so that the program prints:
Rex says Woof
Tom says Meow
Fido says Woof
dogs: 2
Three files to write, one loop to add. Shape, Square and the shapes loop have the same structure.
Step 20 of 21 · Challenge · optional
Challenge: a method for free
Optional. It earns the lesson's third star.
main calls a.describe(), which Animal does not have yet. Give Animal a method describe() that every
animal gets without writing it. The program must print:
Rex says Woof
Tom says Meow
An interface method may have a body when its header starts with default. Every class that implements the
interface gets it.
Inside describe(), call the interface's own methods: name() + " says " + sound().
default String describe() {
return name() + " says " + sound();
}
Step 21 of 21 · Recap
Recap
- An interface names methods. A class that implements it writes them.
- A variable of an interface type may point to any object whose class implements it.
s.area()runs the method of the object it points to: polymorphism.- An abstract class shares fields and code. Its subclasses write its
abstractmethods. s instanceof Circle casks what an object really is.
Next: lesson 16 shows Java's short forms for small classes: enums, records and a new switch.
Review
4 questions from this lesson, in a new order each time. Answer from memory: 3 of 4 right on the first try passes. On a day after you finish the lesson, a pass earns 15 XP.
The review needs JavaScript.
public class Main {
public static void main(String[] args) {
Shape s = new Rectangle(3, 4);
System.out.printf("rectangle: %.2f%n", s.area());
s = new Circle(2);
System.out.printf("circle: %.2f%n", s.area());
}
}
public class Main {
public static void main(String[] args) {
Shape s = new Square(5);
System.out.printf("square: %.2f%n", s.area());
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Shape> shapes = List.of(new Square(2),
new Circle(1), new Rectangle(4, 6));
for (Shape s : shapes) {
System.out.printf("%.2f%n", s.area());
}
}
}
import java.util.List;
public class Main {
static double totalArea(List<Shape> shapes) {
// add up the area of every shape
return 0;
}
public static void main(String[] args) {
List<Shape> shapes = List.of(new Square(2),
new Square(3), new Rectangle(4, 6));
System.out.printf("total: %.2f%n", totalArea(shapes));
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Vehicle> vehicles = List.of(new Bike("Ada"),
new Car("Grace"));
for (Vehicle v : vehicles) {
System.out.println(v.describe());
}
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Shape> shapes = List.of(new Circle(1),
new Rectangle(2, 3), new Circle(3));
for (Shape s : shapes) {
if (s instanceof Circle c) {
double r = c.radius();
System.out.println("a circle of radius " + r);
} else {
System.out.println("another shape");
}
}
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Animal> animals = List.of(new Dog("Rex"),
new Cat("Tom"), new Dog("Fido"));
int dogs = 0;
// for every animal: print its line,
// and count the dogs
System.out.println("dogs: " + dogs);
}
}
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Animal> animals = List.of(new Dog("Rex"),
new Cat("Tom"));
for (Animal a : animals) {
System.out.println(a.describe());
}
}
}