public class AbstractVsInterface {
    public static void main(String[] args) {
        System.out.println("-- abstract class: state, constructor, template method --");
        Report r = new CsvReport("sales");
        System.out.println(r.render());

        System.out.println("-- interface: default, static, private methods --");
        Greeter g = new Greeter() {
            @Override public String name() { return "Ankur"; }
        };
        System.out.println(g.greet());
        System.out.println(Greeter.shout("hello"));

        System.out.println("-- diamond: class must pick one --");
        System.out.println(new Both().hello());

        System.out.println("-- sealed interface + switch --");
        for (Shape s : new Shape[] { new Circle(1), new Square(2) }) {
            System.out.printf("%s area = %.2f%n", s.getClass().getSimpleName(), area(s));
        }
        System.out.println("-- one class, many interfaces; one parent class only --");
        System.out.println(java.util.Arrays.toString(Duck.class.getInterfaces()));
        System.out.println("Duck superclass = " + Duck.class.getSuperclass().getSimpleName());
    }

    static double area(Shape s) {
        return switch (s) {
            case Circle c -> Math.PI * c.r() * c.r();
            case Square q -> q.side() * q.side();
        };
    }
}

abstract class Report {
    protected final String title;
    Report(String title) { this.title = title; System.out.println("Report constructor ran for " + title); }
    abstract String body();
    final String render() { return "== " + title + " ==\n" + body(); }
}
class CsvReport extends Report {
    CsvReport(String t) { super(t); }
    String body() { return "a,b,c"; }
}

interface Greeter {
    String name();
    default String greet() { return decorate("Hi " + name()); }
    static String shout(String s) { return s.toUpperCase() + "!"; }
    private String decorate(String s) { return "[" + s + "]"; }
}

interface A { default String hello() { return "A"; } }
interface B { default String hello() { return "B"; } }
class Both implements A, B {
    @Override public String hello() { return A.super.hello() + "+" + B.super.hello(); }
}

sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double side) implements Shape {}

interface Flyer {}
interface Swimmer {}
class Animal {}
class Duck extends Animal implements Flyer, Swimmer {}
