xSKILLby Infirals
Register

Java for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Abstract classes

Inheritance, interfaces and polymorphism11 min readLesson 4 of 6

4.1 A class that cannot be instantiated

An abstract class declares behavior that subclasses complete. Mark the class abstract; the compiler then rejects new for it. It can still have fields, constructors, and ordinary methods.

An abstract method ends with a semicolon and has no body. Every concrete subclass must implement it, or the subclass must also be abstract. A class with at least one abstract method must be declared abstract.

The abstract type describes a role: a shape has an area, a task has work to do. The base class can hold shared state and leave the variable parts to subclasses.

java
public class Main {
    public static void main(String[] args) {
        Shape shape = new Circle(2);
        System.out.println(shape.area());
        shape.describe();
    }
}
abstract class Shape {
    abstract double area();
    void describe() { System.out.println("Area: " + area()); }
}
class Circle extends Shape {
    double radius;
    Circle(double radius) { this.radius = radius; }
    @Override
    double area() { return 3.14 * radius * radius; }
}

Output

12.56
Area: 12.56

4.1.1 Shared code in the base

An abstract class can implement methods that use its abstract ones. describe() can call area() even though area() has no body yet. The call is resolved on the actual subclass when the method runs.

This is the template method pattern: a concrete method fixes the order of steps, and subclasses fill in the steps. The base class can also mark the template final so a subclass cannot replace the sequence.

Keep the shared code in the base only when it applies to every subclass. If one subclass needs a different version, overriding the concrete method is allowed unless it is final.

java
public class Main {
    public static void main(String[] args) {
        new Report().run();
    }
}
abstract class Task {
    final void run() {
        start();
        work();
        System.out.println("Done");
    }
    void start() { System.out.println("Start"); }
    abstract void work();
}
class Report extends Task {
    @Override
    void work() { System.out.println("Writing report"); }
}

Output

Start
Writing report
Done

4.1.2 Constructors and fields

An abstract class can have constructors, and subclasses call them with super(...). The constructor runs when a subclass object is created, even though the abstract class itself is never instantiated.

Fields declared in the abstract class are available to subclasses through protected access or getters. A private field with a protected getter keeps the value under the base class's control.

Do not put every field in the base class. Move a field down when only one subclass uses it. The base class should describe what all subclasses share.

java
public class Main {
    public static void main(String[] args) {
        Employee employee = new Manager("Ravi", 4);
        employee.printRole();
    }
}
abstract class Employee {
    String name;
    Employee(String name) { this.name = name; }
    abstract String role();
    void printRole() { System.out.println(name + ": " + role()); }
}
class Manager extends Employee {
    int reports;
    Manager(String name, int reports) { super(name); this.reports = reports; }
    @Override
    String role() { return "manager of " + reports; }
}

Output

Ravi: manager of 4

4.1.3 Abstract type as a parameter

A method can accept the abstract type and work with any subclass: printArea(Shape shape). The method calls area(), and each object supplies its own version. Adding a subclass does not change the method.

This is polymorphism in a practical form. The parameter type states what the method needs, and the object provides the behavior. The method stays small and testable.

The same idea works for arrays and lists of the abstract type. A loop over Shape[] can process circles and squares with one call.

java
public class Main {
    public static void main(String[] args) {
        printArea(new Circle(1));
        printArea(new Square(3));
    }
    static void printArea(Shape shape) {
        System.out.printf("%.2f%n", shape.area());
    }
}
abstract class Shape { abstract double area(); }
class Circle extends Shape {
    double radius;
    Circle(double radius) { this.radius = radius; }
    double area() { return 3.14 * radius * radius; }
}
class Square extends Shape {
    double side;
    Square(double side) { this.side = side; }
    double area() { return side * side; }
}

Output

3.14
9.00

4.1.4 Choosing an abstract class

Use an abstract class when subclasses share fields, constructors, or concrete methods, and when a partial implementation makes sense. Java allows one superclass, so the choice also uses up the single inheritance slot.

An interface is a better fit when the contract is a capability that unrelated classes can implement, or when a class needs several contracts. Interfaces can have default methods, which cover some shared behavior without a superclass.

If the base class has no state and no shared implementation, an interface is usually the simpler description. The next lesson covers interfaces in detail.

java
public class Main {
    public static void main(String[] args) {
        System.out.println(new Circle(2));
    }
}
abstract class Shape {
    abstract double area();
    @Override
    public String toString() { return "area=" + area(); }
}
class Circle extends Shape {
    double radius;
    Circle(double radius) { this.radius = radius; }
    double area() { return 3.14 * radius * radius; }
}

Output

area=12.56

4.1.5 Practice

  1. Create an abstract Shape with abstract area() and a concrete describe().
  2. Add Circle and Square, then print each area and description.
  3. Add a constructor to Shape that stores a name, and pass it from both subclasses.
  4. Write a method printArea(Shape shape) and call it with both objects.
  5. Try new Shape() and read the compiler error. Then try a subclass that omits area() and read that error too.

For step 5, the two errors mention different problems. The first objects to creating an abstract type, and the second asks the subclass to implement the missing method.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01Can you create an object of an abstract class?

    No. The compiler rejects `new` on an abstract class. A subclass object still runs the abstract class's constructor through `super(...)`.

  • 02What must a concrete subclass do with inherited abstract methods?

    It must implement each one with a compatible signature and return type, or be declared abstract itself.

  • 03When is an abstract class a better fit than an interface?

    When subclasses share fields, constructors, or concrete code. Java allows one superclass, so it also suits a single family of related types.