Java > Object-Oriented Programming (OOP) > Abstraction > Abstract Classes
Abstract Class Example: Shape Hierarchy
This example demonstrates abstraction using abstract classes in Java. We define an abstract `Shape` class with common properties and methods. Concrete shape classes (e.g., `Circle`, `Rectangle`) extend the abstract class and provide implementations for the abstract methods. This hides the complexity of shape calculations behind a simple interface.
Code Snippet: Abstract Shape Class and Concrete Implementations
The `Shape` class is declared as `abstract`, meaning it cannot be instantiated directly. It contains an abstract method `getArea()` and `getDescription()` which forces subclasses to provide their specific implementations for calculating the area and description. The `Circle` and `Rectangle` classes extend `Shape` and provide concrete implementations for `getArea()` based on their specific formulas. The `getColor` method is a concrete method that can be inherited by all subclasses.
// Abstract Shape class
abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Abstract method to calculate area (must be implemented by subclasses)
public abstract double getArea();
// Concrete method that all shapes inherit
public String getColor() {
return color;
}
public abstract String getDescription();
}
// Circle class extending Shape
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public String getDescription(){
return "This is a circle with radius: " + radius + " and color: " + getColor();
}
}
// Rectangle class extending Shape
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
@Override
public String getDescription(){
return "This is a rectangle with width: " + width + ", height: " + height + " and color: " + getColor();
}
}
// Example usage
public class Main {
public static void main(String[] args) {
Shape circle = new Circle("Red", 5.0);
Shape rectangle = new Rectangle("Blue", 4.0, 6.0);
System.out.println("Circle Area: " + circle.getArea());
System.out.println(circle.getDescription());
System.out.println("Rectangle Area: " + rectangle.getArea());
System.out.println(rectangle.getDescription());
}
}
Concepts Behind the Snippet
Real-Life Use Case
Consider a drawing application. You might have various shapes like circles, squares, triangles, etc. You could define an abstract `Shape` class with methods like `draw()`, `setColor()`, and `getArea()`. Each concrete shape class would then implement the `draw()` method to draw itself on the screen. The application can then treat all shapes as `Shape` objects, simplifying drawing and manipulation logic.
Best Practices
Interview Tip
Be prepared to explain the difference between abstract classes and interfaces in Java. Abstract classes can have concrete methods, while interfaces cannot (until Java 8). A class can implement multiple interfaces, but it can only extend one abstract class.
When to Use Them
Use abstract classes when you have a clear 'is-a' relationship between classes (e.g., a `Circle` *is a* `Shape`). Also, use them when you want to provide some default behavior in the base class (using concrete methods) while forcing subclasses to implement specific behaviors (using abstract methods).
Memory Footprint
Abstract classes themselves don't directly contribute to memory footprint because they cannot be instantiated. However, the subclasses that extend the abstract class will have a memory footprint based on their own fields and the fields they inherit from the abstract class. The memory footprint will be similar to using a regular class with inheritance.
Alternatives
Pros
Cons
FAQ
-
Can an abstract class have a constructor?
Yes, abstract classes can have constructors. The constructor is used to initialize the state of the abstract class when a subclass is instantiated. The subclass must call the superclass constructor using `super()`. -
Can an abstract method be private?
No, abstract methods cannot be private. Abstract methods must be implemented by subclasses, and private methods are not accessible to subclasses. -
Can I create an instance of an abstract class?
No, you cannot directly create an instance of an abstract class. You can only create instances of concrete subclasses that extend the abstract class. -
What happens if a subclass doesn't implement all abstract methods of an abstract class?
If a subclass doesn't implement all abstract methods of its abstract superclass, then the subclass must also be declared as abstract.