Chapter 11: Abstract Classes & Interfaces

What does Abstract mean?

Abstract in English means → existing in thought or as an idea without concrete existence.

In Java, abstract classes and methods provide a way to achieve abstraction - hiding implementation details while showing only essential features.

Abstract Method

A method that is declared without an implementation.

abstract void moveTo(double x, double y);

Abstract Class

If a class includes abstract methods, then the class itself must be declared abstract.

AbstractExample.java
public abstract class PhoneModel {
    String brand;
    String model;
    
    // Concrete method
    public void displayInfo() {
        System.out.println("Brand: " + brand + ", Model: " + model);
    }
    
    // Abstract method - must be implemented by subclasses
    abstract void switchOff();
    abstract void makeCall(String number);
}

class SmartPhone extends PhoneModel {
    @Override
    void switchOff() {
        System.out.println("Smart phone is switching off with animation");
    }
    
    @Override
    void makeCall(String number) {
        System.out.println("Calling " + number + " using touch interface");
    }
    
    // Additional method specific to smartphone
    void browseInternet() {
        System.out.println("Browsing internet on smartphone");
    }
}

class BasicPhone extends PhoneModel {
    @Override
    void switchOff() {
        System.out.println("Basic phone is switching off");
    }
    
    @Override
    void makeCall(String number) {
        System.out.println("Calling " + number + " using keypad");
    }
}

Abstract Class Example

Shape (Abstract)
Circle
Rectangle
Triangle

Important Notes:

  • It is possible to create reference of an abstract class
  • It is NOT possible to create an object of an abstract class
  • We can assign reference of an abstract class to the object of a concrete subclass
  • Working with Abstract Classes

    ShapeExample.java
    abstract class Shape {
        String color;
        
        // Constructor in abstract class
        public Shape(String color) {
            this.color = color;
        }
        
        // Concrete method
        public void displayColor() {
            System.out.println("Color: " + color);
        }
        
        // Abstract methods
        abstract double calculateArea();
        abstract double calculatePerimeter();
        abstract void draw();
    }
    
    class Circle extends Shape {
        private double radius;
        
        public Circle(String color, double radius) {
            super(color);
            this.radius = radius;
        }
        
        @Override
        double calculateArea() {
            return Math.PI * radius * radius;
        }
        
        @Override
        double calculatePerimeter() {
            return 2 * Math.PI * radius;
        }
        
        @Override
        void draw() {
            System.out.println("Drawing a circle with radius " + radius);
        }
    }
    
    class Rectangle extends Shape {
        private double length, width;
        
        public Rectangle(String color, double length, double width) {
            super(color);
            this.length = length;
            this.width = width;
        }
        
        @Override
        double calculateArea() {
            return length * width;
        }
        
        @Override
        double calculatePerimeter() {
            return 2 * (length + width);
        }
        
        @Override
        void draw() {
            System.out.println("Drawing a rectangle " + length + "x" + width);
        }
    }
    
    public class ShapeExample {
        public static void main(String[] args) {
            // Shape shape = new Shape("Red"); // Error - cannot instantiate abstract class
            
            Shape circle = new Circle("Red", 5.0);
            Shape rectangle = new Rectangle("Blue", 4.0, 6.0);
            
            circle.displayColor();
            circle.draw();
            System.out.println("Area: " + circle.calculateArea());
            
            rectangle.displayColor();
            rectangle.draw();
            System.out.println("Area: " + rectangle.calculateArea());
        }
    }

    Interfaces in Java

    Interface in English is a point where two systems meet and interact.

    In Java, interface is a group of related methods with empty bodies (abstract methods).

    Interface Concept

    TV

    System 1

    Buttons

    Interface

    Human

    System 2

    InterfaceExample.java
    interface Bicycle {
        // All methods in interface are public and abstract by default
        void applyBrake(int decrement);
        void speedUp(int increment);
        
        // Constants in interface are public, static, final by default
        int MAX_SPEED = 100;
    }
    
    class AvonCycle implements Bicycle {
        int speed = 7;
        
        @Override
        public void applyBrake(int decrement) {
            speed = speed - decrement;
            System.out.println("Brake applied. Current speed: " + speed);
        }
        
        @Override
        public void speedUp(int increment) {
            speed = speed + increment;
            System.out.println("Speed increased. Current speed: " + speed);
        }
        
        public void displaySpeed() {
            System.out.println("Current speed: " + speed);
        }
    }
    
    public class InterfaceExample {
        public static void main(String[] args) {
            AvonCycle cycle = new AvonCycle();
            cycle.displaySpeed();
            cycle.speedUp(10);
            cycle.applyBrake(5);
            
            System.out.println("Max speed allowed: " + Bicycle.MAX_SPEED);
        }
    }

    Interface Characteristics

  • All methods are public and abstract by default
  • All variables are public, static, and final
  • Cannot have constructors
  • Cannot be instantiated
  • Can be implemented by multiple classes
  • Interface vs Abstract Class

  • Can implement multiple interfaces
  • Cannot extend multiple abstract classes
  • Interfaces support dynamic method dispatch
  • Used for achieving runtime polymorphism
  • Multiple Inheritance with Interfaces

    Is multiple inheritance allowed in Java?

    Multiple inheritance faces problems when there exist methods with same signature in both the super classes. Due to such problems, Java does not support multiple inheritance directly but the similar concept can be achieved using Interfaces.

    MultipleInheritance.java
    interface GPS {
        void showLocation();
        void navigate(String destination);
    }
    
    interface Camera {
        void takePhoto();
        void recordVideo();
    }
    
    interface MediaPlayer {
        void playMusic();
        void playVideo();
    }
    
    // A class can implement multiple interfaces
    class SmartPhone implements GPS, Camera, MediaPlayer {
        String brand;
        
        public SmartPhone(String brand) {
            this.brand = brand;
        }
        
        // GPS interface methods
        @Override
        public void showLocation() {
            System.out.println(brand + " showing current location");
        }
        
        @Override
        public void navigate(String destination) {
            System.out.println(brand + " navigating to " + destination);
        }
        
        // Camera interface methods
        @Override
        public void takePhoto() {
            System.out.println(brand + " taking photo");
        }
        
        @Override
        public void recordVideo() {
            System.out.println(brand + " recording video");
        }
        
        // MediaPlayer interface methods
        @Override
        public void playMusic() {
            System.out.println(brand + " playing music");
        }
        
        @Override
        public void playVideo() {
            System.out.println(brand + " playing video");
        }
    }
    
    public class MultipleInheritance {
        public static void main(String[] args) {
            SmartPhone phone = new SmartPhone("iPhone");
            
            // Using GPS functionality
            phone.showLocation();
            phone.navigate("New York");
            
            // Using Camera functionality
            phone.takePhoto();
            phone.recordVideo();
            
            // Using MediaPlayer functionality
            phone.playMusic();
            phone.playVideo();
            
            // Polymorphism with interfaces
            GPS gps = new SmartPhone("Android");
            gps.showLocation(); // Can only use GPS methods
        }
    }

    Key Points:

  • A class can implement multiple interfaces and extend a class at the same time
  • Interface methods are public by default
  • You can create a reference of interfaces but not the object
  • Classes implementing the interface need to declare all the methods (not fields)
  • Default Methods

    An interface can have static and default methods.

    Default methods enable us to add new functionality to existing interfaces. This feature was introduced in Java 8 to ensure backward compatibility while updating an interface.

    DefaultMethods.java
    interface Vehicle {
        // Abstract method
        void start();
        void stop();
        
        // Default method (Java 8+)
        default void honk() {
            System.out.println("Vehicle is honking");
        }
        
        // Static method (Java 8+)
        static void checkTraffic() {
            System.out.println("Checking traffic conditions");
        }
        
        // Private method (Java 9+) - can be used by default methods
        private void performSafetyCheck() {
            System.out.println("Performing safety check");
        }
        
        default void startSafely() {
            performSafetyCheck(); // Using private method
            start();
        }
    }
    
    class Car implements Vehicle {
        @Override
        public void start() {
            System.out.println("Car engine started");
        }
        
        @Override
        public void stop() {
            System.out.println("Car stopped");
        }
        
        // Can override default method if needed
        @Override
        public void honk() {
            System.out.println("Car horn: Beep! Beep!");
        }
    }
    
    class Motorcycle implements Vehicle {
        @Override
        public void start() {
            System.out.println("Motorcycle engine started");
        }
        
        @Override
        public void stop() {
            System.out.println("Motorcycle stopped");
        }
        
        // Using default honk method (not overriding)
    }
    
    public class DefaultMethods {
        public static void main(String[] args) {
            Car car = new Car();
            Motorcycle bike = new Motorcycle();
            
            car.startSafely();
            car.honk(); // Overridden method
            
            bike.startSafely();
            bike.honk(); // Default method
            
            // Static method call
            Vehicle.checkTraffic();
        }
    }

    Benefits of Default Methods:

  • Classes implementing the interface need not implement the default methods
  • Interfaces can also include private methods for default methods to use
  • Enables backward compatibility when adding new methods to interfaces
  • Reduces code duplication across implementing classes
  • Inheritance in Interfaces

    Interfaces can extend another interfaces.

    Remember that interface cannot implement another interface, only classes can do that!

    InterfaceInheritance.java
    interface BasicPhone {
        void makeCall(String number);
        void receiveCall();
    }
    
    interface SmartPhoneInterface extends BasicPhone {
        void browseInternet();
        void takePhoto();
        void sendEmail(String email);
    }
    
    interface AdvancedSmartPhone extends SmartPhoneInterface {
        void faceRecognition();
        void wirelessCharging();
        void artificialIntelligence();
    }
    
    class iPhone implements AdvancedSmartPhone {
        @Override
        public void makeCall(String number) {
            System.out.println("iPhone calling " + number);
        }
        
        @Override
        public void receiveCall() {
            System.out.println("iPhone receiving call");
        }
        
        @Override
        public void browseInternet() {
            System.out.println("iPhone browsing internet with Safari");
        }
        
        @Override
        public void takePhoto() {
            System.out.println("iPhone taking high-quality photo");
        }
        
        @Override
        public void sendEmail(String email) {
            System.out.println("iPhone sending email to " + email);
        }
        
        @Override
        public void faceRecognition() {
            System.out.println("iPhone using Face ID");
        }
        
        @Override
        public void wirelessCharging() {
            System.out.println("iPhone charging wirelessly");
        }
        
        @Override
        public void artificialIntelligence() {
            System.out.println("iPhone using Siri AI");
        }
    }
    
    public class InterfaceInheritance {
        public static void main(String[] args) {
            iPhone phone = new iPhone();
            
            // Can use all inherited methods
            phone.makeCall("123-456-7890");
            phone.browseInternet();
            phone.faceRecognition();
            
            // Polymorphism with interface hierarchy
            BasicPhone basicPhone = new iPhone();
            basicPhone.makeCall("987-654-3210"); // Can only use BasicPhone methods
            
            SmartPhoneInterface smartPhone = new iPhone();
            smartPhone.takePhoto(); // Can use BasicPhone + SmartPhoneInterface methods
        }
    }

    Polymorphism using Interfaces

    Cell Phone

    Interface

    GPS

    Interface

    Camera

    Interface

    Media Player

    Interface

    Smart Phone

    Class (implements all)

    Similar to Dynamic method dispatch in Inheritance

    Practice Set

    Chapter 11 - Practice Set

    1. Abstract Pen Class

    Create an abstract class Pen with methods write() and refill() as abstract methods.

    2. Fountain Pen Class

    Use the Pen class from #1 to create a concrete class FountainPen with additional method changeNib().

    3. Monkey and Human

    Create a class Monkey with jump() and bite() methods. Create a class Human which inherits this Monkey class and implements BasicAnimal interface with eat() and sleep() methods.

    4. Telephone Classes

    Create a class Telephone with ring(), lift() and disconnect() methods as abstract methods. Create another class SmartTelephone and demonstrate polymorphism.

    5. Polymorphism Demo

    Demonstrate polymorphism using monkey class from #3.

    6. TV Remote Interfaces

    Create an interface TVRemote and use it to inherit another interface SmartTVRemote.

    7. TV Class

    Create a class TV which implements TVRemote interface from #6.

    Solution Example: Abstract Pen and Fountain Pen

    ← Previous: Inheritance Next: Packages →