Java Abstraction
Java - Abstraction
Section titled “Java - Abstraction”Abstraction is one of the core concepts of Object-Oriented Programming (OOP). It focuses on hiding complex implementation details and exposing only the essential features or functionalities of an object or system.
Think about driving a car: you interact with essential controls like the steering wheel, accelerator, and brakes (abstraction), without needing to know the intricate details of the engine’s internal combustion or the braking system’s hydraulics (implementation details).
In Java, abstraction is primarily achieved using:
- Abstract Classes: Classes that cannot be instantiated and may contain abstract methods.
- Interfaces: Reference types that define a contract of abstract methods (and potentially default/static methods).
This chapter focuses on Abstract Classes.
Abstract Classes
Section titled “Abstract Classes”An abstract class serves as a template or blueprint for other classes. It is declared using the abstract keyword.
Key properties of abstract classes:
Section titled “Key properties of abstract classes:”- Cannot be Instantiated: You cannot create an object directly from an abstract class using the
newkeyword. - Can Have Abstract Methods: Methods declared with the
abstractkeyword and without an implementation (no method body, ends with a semicolon). If a class contains even one abstract method, the class itself must be declared abstract. - Can Have Concrete Methods: Can contain regular methods with implementations.
- Can Have Constructors: Abstract classes can have constructors, which are called when an instance of a concrete subclass is created (typically via
super()call from the subclass constructor). - Can Have Fields: Can have instance variables (state) and static variables.
- Subclassing: Designed to be subclassed (extended). Concrete (non-abstract) subclasses must provide implementations for all inherited abstract methods.
Why Use Abstract Classes?
Section titled “Why Use Abstract Classes?”- Code Reusability: Provide common fields and method implementations that subclasses can inherit.
- Enforce Structure: Define a common structure and required methods (abstract methods) that all subclasses must implement, ensuring consistency.
- Template Design: Act as a base for related classes, defining a general concept or entity that is too abstract to exist on its own but provides a foundation for specific types.
- Polymorphism: Allow treating objects of different subclasses through a reference of the abstract class type.
Declaring an Abstract Class
Section titled “Declaring an Abstract Class”Use the abstract keyword before the class keyword.
Example: Abstract Shape Class
Section titled “Example: Abstract Shape Class”/* FileName: Shape.java */
public abstract class Shape { private String color;
// Constructor (called by subclasses) public Shape(String color) { System.out.println("Shape constructor called for color: " + color); this.color = color; }
// Concrete method (shared implementation) public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
// Abstract method (must be implemented by concrete subclasses) public abstract double calculateArea();
// Another abstract method public abstract void draw();}Trying to instantiate an abstract class results in a compile-time error:
// This will cause a compilation error:// Shape myShape = new Shape("Red"); // Error: Shape is abstract; cannot be instantiatedExtending an Abstract Class
Section titled “Extending an Abstract Class”A concrete class extends an abstract class using the extends keyword. It must provide implementations for all abstract methods inherited from the abstract parent class. Use the @Override annotation for clarity and compiler checks.
Example: Concrete Circle Subclass
Section titled “Example: Concrete Circle Subclass”/* FileName: Circle.java */
public class Circle extends Shape { // Extends the abstract Shape class private double radius;
public Circle(String color, double radius) { super(color); // Call the constructor of the abstract parent class System.out.println("Circle constructor called."); this.radius = radius; }
public double getRadius() { return radius; }
// Implementation of the abstract method from Shape @Override public double calculateArea() { return Math.PI * radius * radius; }
// Implementation of the other abstract method from Shape @Override public void draw() { System.out.println("Drawing a " + getColor() + " circle with radius " + radius); }}Example: Concrete Rectangle Subclass
Section titled “Example: Concrete Rectangle Subclass”/* FileName: Rectangle.java */
public class Rectangle extends Shape { private double width; private double height;
public Rectangle(String color, double width, double height) { super(color); System.out.println("Rectangle constructor called."); this.width = width; this.height = height; }
@Override public double calculateArea() { return width * height; }
@Override public void draw() { System.out.println("Drawing a " + getColor() + " rectangle with width " + width + " and height " + height); }}Using Abstract Classes and Subclasses (Polymorphism)
Section titled “Using Abstract Classes and Subclasses (Polymorphism)”You can create objects of the concrete subclasses and use polymorphism to refer to them using the abstract class type.
/* FileName: AbstractionDemo.java */
public class AbstractionDemo { public static void main(String[] args) { // Cannot create Shape object: Shape s1 = new Shape("Blue"); // Error!
// Create objects of concrete subclasses Shape circle = new Circle("Red", 5.0); Shape rectangle = new Rectangle("Blue", 4.0, 6.0);
System.out.println("\n--- Circle Info ---"); System.out.println("Color: " + circle.getColor()); // Inherited concrete method System.out.println("Area: " + circle.calculateArea()); // Overridden abstract method circle.draw(); // Overridden abstract method // circle.getRadius(); // Error: getRadius() is not in Shape. Need casting: if (circle instanceof Circle) { Circle c = (Circle) circle; System.out.println("Radius: " + c.getRadius()); }
System.out.println("\n--- Rectangle Info ---"); System.out.println("Color: " + rectangle.getColor()); System.out.println("Area: " + rectangle.calculateArea()); rectangle.draw();
System.out.println("\n--- Polymorphism with Array ---"); Shape[] shapes = { circle, rectangle, new Circle("Green", 2.5) };
for (Shape currentShape : shapes) { currentShape.draw(); // Calls the specific draw() method of Circle or Rectangle System.out.println("Area: " + currentShape.calculateArea()); System.out.println("--"); } }}Expected Output (Illustrative):
Shape constructor called for color: RedCircle constructor called.Shape constructor called for color: BlueRectangle constructor called.
--- Circle Info ---Color: RedArea: 78.53981633974483Drawing a Red circle with radius 5.0Radius: 5.0
--- Rectangle Info ---Color: BlueArea: 24.0Drawing a Blue rectangle with width 4.0 and height 6.0
--- Polymorphism with Array ---Shape constructor called for color: GreenCircle constructor called.Drawing a Red circle with radius 5.0Area: 78.53981633974483--Drawing a Blue rectangle with width 4.0 and height 6.0Area: 24.0--Drawing a Green circle with radius 2.5Area: 19.634954084936208--Abstract Classes vs. Interfaces
Section titled “Abstract Classes vs. Interfaces”Both abstract classes and interfaces are used for abstraction, but have key differences:
- Inheritance: A class can extend only ONE abstract class, but implement MULTIPLE interfaces.
- Fields: Abstract classes can have instance variables (state). Interfaces primarily have
public static finalconstants (though technically possible to simulate state poorly with default methods, it’s not their intended use). - Methods: Abstract classes can have both abstract and concrete methods. Interfaces have abstract methods, and since Java 8, can also have default (implemented) and static methods.
- Constructors: Abstract classes can have constructors; interfaces cannot.
- Purpose: Use an abstract class for an “is-a” relationship where subclasses share common state and implementation. Use an interface for a “has-a” or “can-do” relationship, defining a capability or contract that potentially unrelated classes can fulfill.