Abstract classes
Some classes make no sense as objects on their own. A "shape in general" cannot calculate its area — only a circle or a square can. Abstract classes exist for such general ideas.
An abstract method
A method marked abstract is declared but not implemented: it has no body, only a header and a semicolon. A class with such a method is marked abstract too, and subclasses must provide the implementation:
abstract class Shape {
abstract double area();
}
class Square extends Shape {
double side;
Square(double side) {
this.side = side;
}
@Override
double area() {
return side * side;
}
}
void main() {
Shape shape = new Square(4);
IO.println(shape.area());
}Output:
16.0Shared code in an abstract class
An abstract class can contain ordinary methods as well. They use the abstract ones, and the subclass supplies the implementation:
abstract class Shape {
abstract double area();
String describe() {
return "A shape with area " + area();
}
}
class Rectangle extends Shape {
double width;
double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
void main() {
IO.println(new Rectangle(2, 3).describe());
}Output:
A shape with area 6.0The describe() method is written once, yet it works for any future shape.
Fields and a constructor
An abstract class may have fields and a constructor. You cannot create its object directly, but the constructor is called from a subclass with super(...):
abstract class Employee {
protected String name;
Employee(String name) {
this.name = name;
}
abstract double salary();
String info() {
return name + ": " + salary() + " €";
}
}
class Developer extends Employee {
Developer(String name) {
super(name);
}
@Override
double salary() {
return 4000;
}
}
class Intern extends Employee {
Intern(String name) {
super(name);
}
@Override
double salary() {
return 1200;
}
}
void main() {
Employee[] team = { new Developer("Anna"), new Intern("Oleg") };
for (Employee e : team) {
IO.println(e.info());
}
}Output:
Anna: 4000.0 €
Oleg: 1200.0 €A subclass must implement everything
If a subclass has not implemented at least one abstract method, it must be abstract too. Otherwise the compiler reports an error and names the missing method:
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
}
void main() {
}Output:
Main.java:5: error: Main.Circle is not abstract and does not override abstract method area() in Main.Shape
class Circle extends Shape {
^When to choose an abstract class
An abstract class fits when related classes share fields and code, and only some steps differ. If there is no shared code and you only need to describe a set of methods, an interface is a better fit — that is the next lesson.
Common mistake
You cannot create an object of an abstract class — it has methods without an implementation:
abstract class Shape {
abstract double area();
}
void main() {
Shape shape = new Shape();
}Output:
Main.java:6: error: Main.Shape is abstract; cannot be instantiated
Shape shape = new Shape();
^Create an object of a concrete subclass; the variable itself can stay of type Shape.