A class can only extend one parent. But a Dog can be both an Animal and a Pet. Interfaces define contracts - a class can implement multiple interfaces, promising to provide certain methods without inheriting implementation.

Basic interface

Define a contract that classes must fulfill.

BasicInterface.java
// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

// Basic Interface Declaration and Implementation

public class BasicInterface {
    public static void main(String[] args) {
        System.out.println("=== Basic Interface ===\n");

        // Cannot instantiate interface!
        // Drawable d = new Drawable();  // ERROR

        // Create implementing classes
        double circleRadius = ;
        double rectangleWidth = ;
        Circle circle = new Circle(circleRadius);
        Rectangle rectangle = new Rectangle(rectangleWidth, 6);

        // Call interface methods
        circle.draw();
        rectangle.draw();

        System.out.println("\n=== Interface as Type ===");

        // Use interface type for reference
        Drawable shape1 = new Circle(3);
        Drawable shape2 = new Rectangle(2, 5);

        shape1.draw();
        shape2.draw();

        System.out.println("\n=== Array of Interface Type ===");

        Drawable[] shapes = {
            new Circle(1),
            new Rectangle(2, 3),
            new Circle(4)
        };

        for (Drawable shape : shapes) {
            shape.draw();
        }

        System.out.println("\n=== Interface Characteristics ===");
        System.out.println("""
        Interface:
        - Cannot be instantiated
        - Methods are public abstract by default
        - Fields are public static final (constants)
        - Classes use 'implements' keyword
        - Implementing class MUST provide all methods
        """);
    }
}

// Interface declaration
interface Drawable {
    // Method declaration - implicitly public abstract
    void draw();

    // Can have multiple methods
    void resize(double factor);

    // Constants - implicitly public static final
    int DEFAULT_SIZE = 10;
}

// Class implements interface
class Circle implements Drawable {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    // MUST implement all interface methods
    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public void resize(double factor) {
        radius *= factor;
        System.out.println("Circle resized to radius " + radius);
    }
}

class Rectangle implements Drawable {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing rectangle " + width + " x " + height);
    }

    @Override
    public void resize(double factor) {
        width *= factor;
        height *= factor;
        System.out.println("Rectangle resized to " + width + " x " + height);
    }
}

interface defines method signatures. No implementation (pre-Java 8).

interface Contract of methods a class must implement. All methods implicitly public abstract.

Implement multiple interfaces

A class can implement many interfaces.

MultipleInterfaces.java
// Implementing Multiple Interfaces

public class MultipleInterfaces {
    public static void main(String[] args) {
        System.out.println("=== Multiple Interfaces ===\n");

        // SmartPhone implements multiple interfaces
        SmartPhone phone = new SmartPhone("iPhone 15");

        System.out.println("--- Using as Camera ---");
        phone.takePhoto();
        phone.recordVideo();

        System.out.println("\n--- Using as Phone ---");
        phone.makeCall("555-1234");
        phone.sendText("Hello!");

        System.out.println("\n--- Using as MediaPlayer ---");
        phone.playMusic("Bohemian Rhapsody");
        phone.playVideo("YouTube clip");

        System.out.println("\n=== Interface References ===");

        // Same object, different interface views
        Camera cam = phone;
        Callable call = phone;
        MediaPlayer player = phone;

        cam.takePhoto();          // Only Camera methods visible
        call.makeCall("555-5678");
        player.playMusic("Song");

        System.out.println("\n=== Duck Typing with Interfaces ===");

        // Different devices, same interfaces
        Camera[] cameras = {
            new SmartPhone("Pixel"),
            new DigitalCamera("Canon"),
        };

        for (Camera c : cameras) {
            c.takePhoto();
        }
    }
}

// Interface 1
interface Camera {
    void takePhoto();
    void recordVideo();
}

// Interface 2
interface Callable {
    void makeCall(String number);
    void sendText(String message);
}

// Interface 3
interface MediaPlayer {
    void playMusic(String song);
    void playVideo(String video);
}

// Class implementing MULTIPLE interfaces
class SmartPhone implements Camera, Callable, MediaPlayer {
    private String model;

    SmartPhone(String model) {
        this.model = model;
    }

    // From Camera
    @Override
    public void takePhoto() {
        System.out.println(model + ": 📷 Taking photo");
    }

    @Override
    public void recordVideo() {
        System.out.println(model + ": 🎥 Recording video");
    }

    // From Callable
    @Override
    public void makeCall(String number) {
        System.out.println(model + ": 📞 Calling " + number);
    }

    @Override
    public void sendText(String message) {
        System.out.println(model + ": 💬 Sending: " + message);
    }

    // From MediaPlayer
    @Override
    public void playMusic(String song) {
        System.out.println(model + ": 🎵 Playing " + song);
    }

    @Override
    public void playVideo(String video) {
        System.out.println(model + ": ▶️ Playing " + video);
    }
}

// Another class implementing just Camera
class DigitalCamera implements Camera {
    private String model;

    DigitalCamera(String model) {
        this.model = model;
    }

    @Override
    public void takePhoto() {
        System.out.println(model + " DSLR: 📷 High-quality photo");
    }

    @Override
    public void recordVideo() {
        System.out.println(model + " DSLR: 🎥 4K video recording");
    }
    // No need to implement Callable or MediaPlayer!
}

class X implements A, B, C - must implement all methods from all interfaces.

Interface as type

Use interface type for polymorphism.

InterfaceReference.java
// Using Interface as Type

public class InterfaceReference {
    public static void main(String[] args) {
        System.out.println("=== Interface as Method Parameter ===\n");

        Circle circle = new Circle(5);
        Rectangle rect = new Rectangle(4, 6);

        // Pass different types to same method
        printArea(circle);
        printArea(rect);

        System.out.println("\n=== Interface as Return Type ===");

        // Factory method returns interface type
        String firstShapeType = ;
        Shape shape1 = createShape(firstShapeType, 3);
        Shape shape2 = createShape("rectangle", 4);

        System.out.println("Created: " + shape1.getName());
        System.out.println("Created: " + shape2.getName());

        System.out.println("\n=== Collection of Interface Type ===");

        Shape[] shapes = {
            createShape("circle", 5),
            createShape("rectangle", 3),
            createShape("circle", 2)
        };

        double totalArea = calculateTotalArea(shapes);
        System.out.println("Total area: " + String.format("%.2f", totalArea));

        System.out.println("\n=== Interface Extends Interface ===");

        // 3DShape extends Shape
        Sphere sphere = new Sphere(4);

        System.out.println("Sphere:");
        System.out.println("  Area: " + String.format("%.2f", sphere.getArea()));
        System.out.println("  Volume: " + String.format("%.2f", sphere.getVolume()));

        // Can use as Shape too!
        printArea(sphere);
    }

    // Method with interface parameter
    static void printArea(Shape shape) {
        System.out.println(shape.getName() + " area: " +
                          String.format("%.2f", shape.getArea()));
    }

    // Method with interface return type
    static Shape createShape(String type, double size) {
        return switch(type.toLowerCase()) {
            case "circle" -> new Circle(size);
            case "rectangle" -> new Rectangle(size, size);
            default -> throw new IllegalArgumentException("Unknown shape: " + type);
        };
    }

    // Method processing array of interfaces
    static double calculateTotalArea(Shape[] shapes) {
        double total = 0;
        for (Shape s : shapes) {
            total += s.getArea();
        }
        return total;
    }
}

// Base interface
interface Shape {
    double getArea();
    String getName();
}

// Interface extending interface
interface Shape3D extends Shape {
    double getVolume();
    // Also inherits getArea() and getName()!
}

class Circle implements Shape {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    @Override
    public String getName() {
        return "Circle (r=" + radius + ")";
    }
}

class Rectangle implements Shape {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double getArea() {
        return width * height;
    }

    @Override
    public String getName() {
        return "Rectangle (" + width + "x" + height + ")";
    }
}

// Implements extended interface
class Sphere implements Shape3D {
    private double radius;

    Sphere(double radius) {
        this.radius = radius;
    }

    // From Shape (inherited by Shape3D)
    @Override
    public double getArea() {
        return 4 * Math.PI * radius * radius;  // Surface area
    }

    @Override
    public String getName() {
        return "Sphere (r=" + radius + ")";
    }

    // From Shape3D
    @Override
    public double getVolume() {
        return (4.0 / 3.0) * Math.PI * radius * radius * radius;
    }
}

// Using Interface as Type

public class InterfaceReference {
    public static void main(String[] args) {
        System.out.println("=== Interface as Method Parameter ===\n");

        Circle circle = new Circle(5);
        Rectangle rect = new Rectangle(4, 6);

        // Pass different types to same method
        printArea(circle);
        printArea(rect);

        System.out.println("\n=== Interface as Return Type ===");

        // Factory method returns interface type
        String firstShapeType = ;
        Shape shape1 = createShape(firstShapeType, 3);
        Shape shape2 = createShape("rectangle", 4);

        System.out.println("Created: " + shape1.getName());
        System.out.println("Created: " + shape2.getName());

        System.out.println("\n=== Collection of Interface Type ===");

        Shape[] shapes = {
            createShape("circle", 5),
            createShape("rectangle", 3),
            createShape("circle", 2)
        };

        double totalArea = calculateTotalArea(shapes);
        System.out.println("Total area: " + String.format("%.2f", totalArea));

        System.out.println("\n=== Interface Extends Interface ===");

        // 3DShape extends Shape
        Sphere sphere = new Sphere(4);

        System.out.println("Sphere:");
        System.out.println("  Area: " + String.format("%.2f", sphere.getArea()));
        System.out.println("  Volume: " + String.format("%.2f", sphere.getVolume()));

        // Can use as Shape too!
        printArea(sphere);
    }

    // Method with interface parameter
    static void printArea(Shape shape) {
        System.out.println(shape.getName() + " area: " +
                          String.format("%.2f", shape.getArea()));
    }

    // Method with interface return type
    static Shape createShape(String type, double size) {
        return switch(type.toLowerCase()) {
            case "circle" -> new Circle(size);
            case "rectangle" -> new Rectangle(size, size);
            default -> throw new IllegalArgumentException("Unknown shape: " + type);
        };
    }

    // Method processing array of interfaces
    static double calculateTotalArea(Shape[] shapes) {
        double total = 0;
        for (Shape s : shapes) {
            total += s.getArea();
        }
        return total;
    }
}

// Base interface
interface Shape {
    double getArea();
    String getName();
}

// Interface extending interface
interface Shape3D extends Shape {
    double getVolume();
    // Also inherits getArea() and getName()!
}

class Circle implements Shape {
    private double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    @Override
    public String getName() {
        return "Circle (r=" + radius + ")";
    }
}

class Rectangle implements Shape {
    private double width, height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double getArea() {
        return width * height;
    }

    @Override
    public String getName() {
        return "Rectangle (" + width + "x" + height + ")";
    }
}

// Implements extended interface
class Sphere implements Shape3D {
    private double radius;

    Sphere(double radius) {
        this.radius = radius;
    }

    // From Shape (inherited by Shape3D)
    @Override
    public double getArea() {
        return 4 * Math.PI * radius * radius;  // Surface area
    }

    @Override
    public String getName() {
        return "Sphere (r=" + radius + ")";
    }

    // From Shape3D
    @Override
    public double getVolume() {
        return (4.0 / 3.0) * Math.PI * radius * radius * radius;
    }
}

Drawable d = new Circle() - variable type is interface, object is implementing class.

Default methods

Interfaces can provide default implementations (Java 8+).

DefaultMethods.java
// Default Methods (Java 8+)

public class DefaultMethods {
    public static void main(String[] args) {
        System.out.println("=== Default Methods in Interfaces ===\n");

        // BasicPrinter uses default log()
        BasicPrinter basic = new BasicPrinter();
        basic.print("Hello");
        basic.log("Starting print job");

        System.out.println("\n=== Overriding Default Method ===");

        // AdvancedPrinter overrides log()
        AdvancedPrinter advanced = new AdvancedPrinter();
        advanced.print("Document");
        advanced.log("Print initiated");

        System.out.println("\n=== Static Methods in Interface ===");

        // Call static method on interface
        String version = Printable.getVersion();
        System.out.println("Printable version: " + version);

        System.out.println("\n=== Multiple Interfaces with Same Default ===");

        MultiDevice device = new MultiDevice();
        device.connect();

        System.out.println("\n=== Why Default Methods? ===");
        System.out.println("""
        Before Java 8:
        - Adding method to interface broke all implementations
        - Every class needed updating

        With default methods:
        - Add new methods with default implementation
        - Existing classes still work
        - Optional override for custom behavior

        Real examples:
        - List.sort() - added in Java 8
        - Collection.stream() - added in Java 8
        """);
    }
}

// Interface with default method
interface Printable {
    // Abstract method - must implement
    void print(String content);

    // Default method - optional to override
    default void log(String message) {
        System.out.println("[LOG] " + message);
    }

    // Another default method
    default void preview() {
        System.out.println("Showing preview...");
    }

    // Static method in interface
    static String getVersion() {
        return "1.0";
    }
}

// Uses default implementation
class BasicPrinter implements Printable {

    @Override
    public void print(String content) {
        System.out.println("Printing: " + content);
    }

    // Does NOT override log() - uses default
    // Does NOT override preview() - uses default
}

// Overrides default method
class AdvancedPrinter implements Printable {

    @Override
    public void print(String content) {
        System.out.println("Advanced printing: " + content);
    }

    @Override
    public void log(String message) {
        System.out.println("[ADVANCED LOG] " +
                          java.time.LocalTime.now() + " - " + message);
    }
}

// Two interfaces with same default method
interface USB {
    default void connect() {
        System.out.println("USB connecting...");
    }
}

interface Bluetooth {
    default void connect() {
        System.out.println("Bluetooth connecting...");
    }
}

// Must resolve conflict
class MultiDevice implements USB, Bluetooth {

    @Override
    public void connect() {
        System.out.println("Multi-device connecting:");
        USB.super.connect();
        Bluetooth.super.connect();
    }
}

default void method() { } - provides implementation that classes can inherit or override.

default method Interface method with implementation. Classes inherit it unless they override.

Functional interfaces

Interfaces with exactly one abstract method work with lambdas.

FunctionalInterfaceDemo.java
// Functional Interfaces and Lambdas

public class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        System.out.println("=== Functional Interface ===\n");

        // Traditional: Anonymous inner class
        Calculator add1 = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };

        System.out.println("Anonymous class: 5 + 3 = " + add1.calculate(5, 3));

        // Modern: Lambda expression
        Calculator add2 = (a, b) -> a + b;

        System.out.println("Lambda: 5 + 3 = " + add2.calculate(5, 3));

        System.out.println("\n=== Multiple Operations ===");

        // Different operations, same interface
        Calculator subtract = (a, b) -> a - b;
        Calculator multiply = (a, b) -> a * b;
        Calculator divide = (a, b) -> a / b;
        Calculator max = (a, b) -> a > b ? a : b;

        int x = ;
        int y = ;
        System.out.println(x + " + " + y + " = " + add2.calculate(x, y));
        System.out.println(x + " - " + y + " = " + subtract.calculate(x, y));
        System.out.println(x + " * " + y + " = " + multiply.calculate(x, y));
        System.out.println(x + " / " + y + " = " + divide.calculate(x, y));
        System.out.println("max(" + x + ", " + y + ") = " + max.calculate(x, y));

        System.out.println("\n=== Passing Lambda to Method ===");

        // Pass behavior as parameter
        applyOperation("Addition", 7, 3, (a, b) -> a + b);
        applyOperation("Power", 2, 8, (a, b) -> (int) Math.pow(a, b));

        System.out.println("\n=== Lambda Variations ===");

        // Single parameter
        Greeter hello = name -> "Hello, " + name + "!";
        System.out.println(hello.greet("World"));

        // Multi-line body
        Greeter formal = name -> {
            String title = "Dear " + name;
            return title + ", welcome!";
        };
        System.out.println(formal.greet("Guest"));

        // No parameters
        MessageSupplier supplier = () -> "Generated message at " + System.currentTimeMillis();
        System.out.println(supplier.get());

        System.out.println("\n=== @FunctionalInterface ===");
        System.out.println("""
        @FunctionalInterface annotation:
        - Documents intent
        - Compiler enforces single abstract method
        - Enables lambda usage

        Common built-in functional interfaces:
        - Runnable: () -> void
        - Comparator<T>: (T, T) -> int
        - Consumer<T>: (T) -> void
        - Supplier<T>: () -> T
        - Function<T, R>: (T) -> R
        - Predicate<T>: (T) -> boolean
        """);
    }

    // Method accepting functional interface
    static void applyOperation(String name, int a, int b, Calculator calc) {
        int result = calc.calculate(a, b);
        System.out.println(name + ": " + a + " op " + b + " = " + result);
    }
}

// Functional interface - exactly ONE abstract method
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);

    // Default methods allowed!
    default void printResult(int a, int b) {
        System.out.println("Result: " + calculate(a, b));
    }
}

// Another functional interface
@FunctionalInterface
interface Greeter {
    String greet(String name);
}

@FunctionalInterface
interface MessageSupplier {
    String get();
}

// Functional Interfaces and Lambdas

public class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        System.out.println("=== Functional Interface ===\n");

        // Traditional: Anonymous inner class
        Calculator add1 = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };

        System.out.println("Anonymous class: 5 + 3 = " + add1.calculate(5, 3));

        // Modern: Lambda expression
        Calculator add2 = (a, b) -> a + b;

        System.out.println("Lambda: 5 + 3 = " + add2.calculate(5, 3));

        System.out.println("\n=== Multiple Operations ===");

        // Different operations, same interface
        Calculator subtract = (a, b) -> a - b;
        Calculator multiply = (a, b) -> a * b;
        Calculator divide = (a, b) -> a / b;
        Calculator max = (a, b) -> a > b ? a : b;

        int x = ;
        int y = ;
        System.out.println(x + " + " + y + " = " + add2.calculate(x, y));
        System.out.println(x + " - " + y + " = " + subtract.calculate(x, y));
        System.out.println(x + " * " + y + " = " + multiply.calculate(x, y));
        System.out.println(x + " / " + y + " = " + divide.calculate(x, y));
        System.out.println("max(" + x + ", " + y + ") = " + max.calculate(x, y));

        System.out.println("\n=== Passing Lambda to Method ===");

        // Pass behavior as parameter
        applyOperation("Addition", 7, 3, (a, b) -> a + b);
        applyOperation("Power", 2, 8, (a, b) -> (int) Math.pow(a, b));

        System.out.println("\n=== Lambda Variations ===");

        // Single parameter
        Greeter hello = name -> "Hello, " + name + "!";
        System.out.println(hello.greet("World"));

        // Multi-line body
        Greeter formal = name -> {
            String title = "Dear " + name;
            return title + ", welcome!";
        };
        System.out.println(formal.greet("Guest"));

        // No parameters
        MessageSupplier supplier = () -> "Generated message at " + System.currentTimeMillis();
        System.out.println(supplier.get());

        System.out.println("\n=== @FunctionalInterface ===");
        System.out.println("""
        @FunctionalInterface annotation:
        - Documents intent
        - Compiler enforces single abstract method
        - Enables lambda usage

        Common built-in functional interfaces:
        - Runnable: () -> void
        - Comparator<T>: (T, T) -> int
        - Consumer<T>: (T) -> void
        - Supplier<T>: () -> T
        - Function<T, R>: (T) -> R
        - Predicate<T>: (T) -> boolean
        """);
    }

    // Method accepting functional interface
    static void applyOperation(String name, int a, int b, Calculator calc) {
        int result = calc.calculate(a, b);
        System.out.println(name + ": " + a + " op " + b + " = " + result);
    }
}

// Functional interface - exactly ONE abstract method
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);

    // Default methods allowed!
    default void printResult(int a, int b) {
        System.out.println("Result: " + calculate(a, b));
    }
}

// Another functional interface
@FunctionalInterface
interface Greeter {
    String greet(String name);
}

@FunctionalInterface
interface MessageSupplier {
    String get();
}

// Functional Interfaces and Lambdas

public class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        System.out.println("=== Functional Interface ===\n");

        // Traditional: Anonymous inner class
        Calculator add1 = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };

        System.out.println("Anonymous class: 5 + 3 = " + add1.calculate(5, 3));

        // Modern: Lambda expression
        Calculator add2 = (a, b) -> a + b;

        System.out.println("Lambda: 5 + 3 = " + add2.calculate(5, 3));

        System.out.println("\n=== Multiple Operations ===");

        // Different operations, same interface
        Calculator subtract = (a, b) -> a - b;
        Calculator multiply = (a, b) -> a * b;
        Calculator divide = (a, b) -> a / b;
        Calculator max = (a, b) -> a > b ? a : b;

        int x = ;
        int y = ;
        System.out.println(x + " + " + y + " = " + add2.calculate(x, y));
        System.out.println(x + " - " + y + " = " + subtract.calculate(x, y));
        System.out.println(x + " * " + y + " = " + multiply.calculate(x, y));
        System.out.println(x + " / " + y + " = " + divide.calculate(x, y));
        System.out.println("max(" + x + ", " + y + ") = " + max.calculate(x, y));

        System.out.println("\n=== Passing Lambda to Method ===");

        // Pass behavior as parameter
        applyOperation("Addition", 7, 3, (a, b) -> a + b);
        applyOperation("Power", 2, 8, (a, b) -> (int) Math.pow(a, b));

        System.out.println("\n=== Lambda Variations ===");

        // Single parameter
        Greeter hello = name -> "Hello, " + name + "!";
        System.out.println(hello.greet("World"));

        // Multi-line body
        Greeter formal = name -> {
            String title = "Dear " + name;
            return title + ", welcome!";
        };
        System.out.println(formal.greet("Guest"));

        // No parameters
        MessageSupplier supplier = () -> "Generated message at " + System.currentTimeMillis();
        System.out.println(supplier.get());

        System.out.println("\n=== @FunctionalInterface ===");
        System.out.println("""
        @FunctionalInterface annotation:
        - Documents intent
        - Compiler enforces single abstract method
        - Enables lambda usage

        Common built-in functional interfaces:
        - Runnable: () -> void
        - Comparator<T>: (T, T) -> int
        - Consumer<T>: (T) -> void
        - Supplier<T>: () -> T
        - Function<T, R>: (T) -> R
        - Predicate<T>: (T) -> boolean
        """);
    }

    // Method accepting functional interface
    static void applyOperation(String name, int a, int b, Calculator calc) {
        int result = calc.calculate(a, b);
        System.out.println(name + ": " + a + " op " + b + " = " + result);
    }
}

// Functional interface - exactly ONE abstract method
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);

    // Default methods allowed!
    default void printResult(int a, int b) {
        System.out.println("Result: " + calculate(a, b));
    }
}

// Another functional interface
@FunctionalInterface
interface Greeter {
    String greet(String name);
}

@FunctionalInterface
interface MessageSupplier {
    String get();
}

// Functional Interfaces and Lambdas

public class FunctionalInterfaceDemo {
    public static void main(String[] args) {
        System.out.println("=== Functional Interface ===\n");

        // Traditional: Anonymous inner class
        Calculator add1 = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };

        System.out.println("Anonymous class: 5 + 3 = " + add1.calculate(5, 3));

        // Modern: Lambda expression
        Calculator add2 = (a, b) -> a + b;

        System.out.println("Lambda: 5 + 3 = " + add2.calculate(5, 3));

        System.out.println("\n=== Multiple Operations ===");

        // Different operations, same interface
        Calculator subtract = (a, b) -> a - b;
        Calculator multiply = (a, b) -> a * b;
        Calculator divide = (a, b) -> a / b;
        Calculator max = (a, b) -> a > b ? a : b;

        int x = ;
        int y = ;
        System.out.println(x + " + " + y + " = " + add2.calculate(x, y));
        System.out.println(x + " - " + y + " = " + subtract.calculate(x, y));
        System.out.println(x + " * " + y + " = " + multiply.calculate(x, y));
        System.out.println(x + " / " + y + " = " + divide.calculate(x, y));
        System.out.println("max(" + x + ", " + y + ") = " + max.calculate(x, y));

        System.out.println("\n=== Passing Lambda to Method ===");

        // Pass behavior as parameter
        applyOperation("Addition", 7, 3, (a, b) -> a + b);
        applyOperation("Power", 2, 8, (a, b) -> (int) Math.pow(a, b));

        System.out.println("\n=== Lambda Variations ===");

        // Single parameter
        Greeter hello = name -> "Hello, " + name + "!";
        System.out.println(hello.greet("World"));

        // Multi-line body
        Greeter formal = name -> {
            String title = "Dear " + name;
            return title + ", welcome!";
        };
        System.out.println(formal.greet("Guest"));

        // No parameters
        MessageSupplier supplier = () -> "Generated message at " + System.currentTimeMillis();
        System.out.println(supplier.get());

        System.out.println("\n=== @FunctionalInterface ===");
        System.out.println("""
        @FunctionalInterface annotation:
        - Documents intent
        - Compiler enforces single abstract method
        - Enables lambda usage

        Common built-in functional interfaces:
        - Runnable: () -> void
        - Comparator<T>: (T, T) -> int
        - Consumer<T>: (T) -> void
        - Supplier<T>: () -> T
        - Function<T, R>: (T) -> R
        - Predicate<T>: (T) -> boolean
        """);
    }

    // Method accepting functional interface
    static void applyOperation(String name, int a, int b, Calculator calc) {
        int result = calc.calculate(a, b);
        System.out.println(name + ": " + a + " op " + b + " = " + result);
    }
}

// Functional interface - exactly ONE abstract method
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);

    // Default methods allowed!
    default void printResult(int a, int b) {
        System.out.println("Result: " + calculate(a, b));
    }
}

// Another functional interface
@FunctionalInterface
interface Greeter {
    String greet(String name);
}

@FunctionalInterface
interface MessageSupplier {
    String get();
}

@FunctionalInterface ensures single abstract method. Use with lambdas.

functional interface Interface with one abstract method. Can be implemented with lambda expression.

Exercise: Practical.java

Build a plugin system using interfaces