Inheritance allows us to abstract over a set of classes that have similar structure and behavior.
public class Shape {
public void draw(Graphics g) { ... }
public double area() { ... }
public Point centroid() { ... }
public double distanceTo(Shape other) { ... }
}
public class Circle extends Shape { ... }
public class Triangle extends Shape { ... }
public class Rectangle extends Shape { ... }
Shape
in an abstraction for a number of different kinds
of shapes.
When a subclass defines a method with the same signature as one defined in its superclass.
When that method is invoked on an instance of the subclass, the method defined in the subclass is run rather than the one in the superclass.
Polymorphism, Greek for “many forms”.
To augment the behavior of the superclass.
To fill in behavior of a method in a specific way.
We want to augment behavior when the superclass has useful behavior but we also want to do something else.
Instances of a class need to live up to the contract of the superclass so they can be substituted in anywhere an instance of the superclass could be used.
Some of this is guaranteed by the compiler—the return types have to match, etc.
But other bits are up to you.
super
for methodsTo properly augment behavior, we may need to invoke the superclass version of the same method.
The keyword super
allows us to do that.
public void foo() {
super.foo();
doSomethingElse();
}
super
is kind of like this
, a magic
variable name that refers to the current object but only for the
purpose of invoking a method from the superclass.
public class Student {
// fields and constructors here
public String toString() {
return "Name: " + name + "; Grade: " + grade;
}
}
public class SLCStudent extends Student {
// new fields and constructors here
public String toString() {
return super.toString() + "; SLC: " + slc;
}
}
public class Shape {
public void draw(Graphics2D g) {
// do nothing.
}
}
All Shape
s can be drawn but there’s no way to draw a
completely generic shape so this method does nothing.
But in subclasses we can define meaningful
draw
methods.
public class Circle extends Shape {
public void draw(Graphics2D g) {
g.drawOval(x, y, radius, radius);
}
}
public class Rectangle extends Shape {
public void draw(Graphics2D g) {
g.drawRect(x, y, width, height);
}
}
Often, as here, no useful implementation of a method in the superclass.
This is because Shape
is just an abstraction—it
represents the idea of shapes and what you can do with them but we
can only draw actual, concrete shapes.
We can declare classes and methods abstract
and then
the compiler will make sure that all subclasses actually implement
the necessary methods.
public abstract class Shape {
public abstract void draw(Graphics2D g);
public abstract double area();
}
public abstract class Shape {
public abstract void draw(Graphics2D g);
public abstract double area();
public abstract Point centroid();
public double distanceTo(Shape other) {
Point me = centroid();
Point them = other.centroid();
return Math.hypot(me.x - them.x, me.y - them.y);
}
}
Interfaces—like abstract classes but better.
Actually one of the most important features of Java.
To learn about them, sign up for my advanced course.