In this article, we’ll talk about what is an abstract class in java, why and how you should use it.
1. What is an Abstract Class in Java
You can think of a Java abstract class as a semi-abstracted class, meaning that it is not an interface and at the same time it is not a concrete class. By using abstract classes, you can create partially implemented classes, in order to implement all the unimplemented parts in a child class.
An abstract class can be created by using the abstract
keyword as shown below:
public abstract class Shape
As you should have already guessed, we can never declare a class as final and abstract, since its purpose is to be extended by other classes.
2. Java Abstract Class Members, Constructors and Methods
In this section, we’ll analyze each part of an abstract class, how it works, and what are the rules.
2.1 Abstract Class Members
When it comes to members of an abstract class, there is no difference from a concrete class; this means that you can add members with any access modifier you like.
However, if you do not want to add setters and getters to an abstract class, you have to use the protected keyword.
2.2 Abstract Class Constructor
Since an abstract class is not concrete, you cannot create an object of this type. Nevertheless, you are allowed to create constructors inside the abstract class so that they are used by the subclasses that extend this abstract class.
Consider the example below:
public abstract class Shape { protected String name; protected Shape(String name) { this.name = name; } }
As it has already been stated, you cannot do the following:
Shape shape = new Shape("Shape");
and you will get the following compile error:
java: Shape is abstract; cannot be instantiated
Now, let’s create a class Circle that extends this abstract class:
public class Circle extends Shape { private final double radius; protected Circle (String name) { super(name); this.radius = radius; } }
So now we are able to call the parent constructor when creating a circle object, by writing the following:
Shape shape = new Circle("A Beautiful Circle", 5);
2.3 Abstract Class and Abstract Methods
An abstract method is a method that it does not have an implementation and is meant to be implemented by subclasses. As you can infer, an abstract method can never be declared as final or as static since we will never be able to implement it.
Moreover, an abstract class can have zero, one, or more abstract methods.
Also, when it comes to concrete methods, an abstract class can have zero, one, or more implemented methods, which can be static or non-static.
Last but not least, an important rule is that if you decide not to implement an abstract method in a child class, then this method and class MUST be declared as abstract; let’s enhance our previous example:
public abstract class Shape { protected String name; protected Shape(String name) { this.name = name; } protected abstract double getArea(); protected void printName(){ System.out.println(name); } }
We just added two methods; an abstract and an implemented one.
The next step is to enhance the Circle class:
If we leave the Circle class as-is we will get the following error:
java: Circle is not abstract and does not override abstract method getArea() in Shape
This means that we have two options:
1. Implement the method and annotate it with @Override:
public class Circle extends Shape { private static final double PI = 3.14; private final double radius; protected Circle(String name, double radius) { super(name); this.radius = radius; } @Override protected double getArea() { return PI * Math.pow(radius, 2); } }
Therefore, we can try the following:
Shape shape = new Circle("Nice Circle", 5); System.out.println(shape.getArea());
If we want to access the radius member, then we have to declare the
Circle
as of typeCircle
and notShape
, since the type of the object dictates which methods can be called. You can read more about that in Polymorphism in Java.
2. Declare the Circle class as abstract:
We just have to write public abstract class Circle extends Shape {
and we will not have to implement the method inside this class. This chain of abstract classes will only stop if we choose to implement all abstract methods.
3. Java Abstract Class Example
In this section, we will enhance the Shape example even more, by adding more methods and implementations:
Shape.java:
public abstract class Shape { protected String name; protected Shape(String name) { this.name = name; } protected abstract double getArea(); protected abstract double getPerimeter(); protected void printName(){ System.out.println(name); } }
Circle.java:
public class Circle extends Shape { private static final double PI = 3.14; private final double radius; protected Circle(String name, double radius) { super(name); this.radius = radius; } @Override protected double getArea() { return PI * Math.pow(radius, 2); } @Override protected double getPerimeter() { return 2 * PI * radius; } }
Triangle.java:
public class Triangle extends Shape { private double firstSide; private double secondSide; private double base; private double height; protected Triangle(String name, double firstSide, double secondSide, double base, double height) { super(name); this.firstSide = firstSide; this.secondSide = secondSide; this.base = base; this.height = height; } @Override protected double getArea() { return (base * height) / 2; } @Override protected double getPerimeter() { return firstSide + secondSide + base; } }
Then, we can try creating some shapes to try the code:
Shape circleA = new Circle("A", 5); Shape triangleA = new Triangle("A", 2, 4, 5, 4); System.out.println(circleA.getArea()); System.out.println(circleA.getPerimeter()); System.out.println(triangleA.getArea()); System.out.println(triangleA.getPerimeter());
The output will be:
78.5 31.400000000000002 10.0 11.0
Finally, we can create another implementation anywhere, for example, let’s create a Square implementation:
Shape square = new Shape("A Square with side == 5") { @Override protected double getArea() { return 5 * 5; } @Override protected double getPerimeter() { return 5 * 4; } }; System.out.println(square.getPerimeter()); System.out.println(square.getArea());
This will print 20 and 25. As you can observe, we cannot reuse this implementation as we did with Triangle
and Circle
.
4. Java Abstract Class vs Interface
Below you can find a comparison table between an abstract class and an interface:
Abstract Class | Interface |
---|---|
Members can have any access modifier, they can be static or non-static and they can be final or non-final | Members can only be public static final(constants) |
An abstract class can have many constructors | An interface cannot have any constructors |
Non-static concrete methods can have any access modifier | Non-static concrete methods can have the private access modifier only |
Static concrete methods can have any access modifier | Static concrete methods can only be private or public |
You cannot create default methods | You can create default methods |
You need to explicitly write the abstract keyword to declare an abstract method. | All methods that do not have any access modifier and are not static, are considered as public abstract by default. |
A subclass can only extend one abstract class | A subclass can implement multiple interfaces |
To extend an abstrac class you use the extends keyword | To implement an interface you use the implements keyword |
It is intended to provide partial abstraction | It is intended to provide full abstraction |
5. Conclusion
By now you should know what an abstract class is, what are its unique characteristics and its differences from an interface. Should you like to learn more about Interfaces, check this article. Last but not least, you can find the source code on our GitHub page.