Home
5Abstract Classes & Interfaces
5

Lab Manual V · CSE 202

Abstract Classes & Interfaces

Use an abstract Animal class for shared state and required behaviour, and the Drawable and Eatable interfaces for optional capabilities, then treat objects through both kinds of reference.

← → move between slides · F full screen · M slide list

Before we start

Why this lab

Every animal makes a sound, but there is no such thing as a plain “animal” sound. And only some animals can be drawn on screen or eaten. How do we say that in Java?

An abstract class says “every animal must…”; an interface says “this one can also…”. Dog, Bird and Fish combine both.

Lab 5 of 10

Lab at a glance

After this lab you can

  • Explain the purpose of abstract classes and declare them with abstract
  • Implement abstract methods in concrete subclasses
  • Define interfaces as behavioural contracts and implement them
  • Choose between an abstract class and an interface
  • Use abstract-class and interface references polymorphically
  • Check interface implementation with instanceof

Before you start

  • Lab 4: inheritance, extends, super, overriding, polymorphism

Plan for the session

  1. Theory recap
  2. Walk through the program, section by section, and run it
  3. In-lab tasks, shown to the instructor
  4. Report exercises at home

Theory 1 of 5

Abstract classes and methods

public abstract class Animal {
    protected String name;
    protected int age;

    protected Animal(String name, int age) { ... }

    public abstract void makeSound();   // no body
    public abstract void eat();

    public void displayInfo() { ... }   // shared code
}
  • An abstract class cannot be instantiated: new Animal(…) is a compile error.
  • Concrete subclasses must implement every abstract method (or be abstract themselves).
  • It can still have fields, constructors (called with super) and normal methods.

Theory 2 of 5

Interfaces

public interface Drawable {
    void draw();
    void hide();
}

public class Dog extends Animal implements Drawable { ... }
  • An interface lists methods an implementing class promises to provide.
  • A class extends one class but may implement many interfaces: implements Drawable, Eatable.

Theory 3 of 5

The lab’s design

  • Dog and Bird are Animals that can be drawn; Fish is an Animal that can be eaten.

Theory 4 of 5

Abstract class or interface?

Abstract classInterface
Relationshipis-a (Dog is an Animal)can-do (Dog can be drawn)
Statefields and constructorsconstants only
Inheritanceextend oneimplement many
Use whenrelated classes share codeunrelated classes share behaviour

Theory 5 of 5

Polymorphism through both reference types

Animal[]   animals   = {dog, bird, fish};
Drawable[] drawables = {dog, bird};

if (animal instanceof Drawable) {
    ((Drawable) animal).draw();
}
  • An Animal reference can call makeSound() and eat(); a Drawable reference can call draw() and hide().
  • instanceof works with interfaces too.

Implementation design

Execution flow

  1. Create a Dog, a Bird and a Fish
  2. Loop over an Animal[]: displayInfo(), makeSound(), eat()
  3. Loop over a Drawable[]: draw(), hide()
  4. Use the Fish through an Eatable reference
  5. Show that Animal cannot be instantiated
  6. Test instanceof with both interfaces
  7. Cast an Animal reference back to Dog

Animal holds shared state and forces sound/eat; interfaces add optional capabilities.

Code walkthrough 1 of 8 · Animal.java

An abstract class

public abstract class Animal {

    protected String name;
    protected int age;

    protected Animal(String name, int age) {
        this.name = name;
        if (age >= 0) {
            this.age = age;
        } else {
            this.age = 0;
        }
    }

    public abstract void makeSound();

    public abstract void eat();
  • Shared fields and a constructor, plus two methods with no body.
  • Every concrete subclass must implement makeSound() and eat().

Code walkthrough 2 of 8 · Drawable.java · Eatable.java

Two interfaces

public interface Drawable {
    void draw();
    void hide();
}

public interface Eatable {
    boolean isPoisonous();
    int getNutrition();
}
  • Contracts only: method names, no state.
  • A class lists the ones it supports with implements.

Code walkthrough 3 of 8 · Dog.java

Dog: extends one, implements one

public class Dog extends Animal implements Drawable {

    private String breed;

    public Dog(String name, int age, String breed) {
        super(name, age);
        this.breed = breed;
    }

    @Override
    public void makeSound() {

Code walkthrough 3 of 8 · Dog.java

Dog: extends one, implements one (cont.)

        System.out.println(name + " barks: Woof! Woof!");
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating dog food from a bowl.");
    }
  • extends Animal implements Drawable: one superclass, any number of interfaces.
  • First, the two abstract methods from Animal.

Code walkthrough 4 of 8 · Dog.java

Dog keeps the Drawable contract

@Override
public void draw() {
    System.out.println("[Drawing] " + name + " (" + breed + ") as a dog.");
}

@Override
public void hide() {
    System.out.println("[Hiding] " + name + " is no longer visible.");
}
  • Without draw() and hide(), Dog would not compile: it promised to be Drawable.

Code walkthrough 5 of 8 · Fish.java

Fish implements Eatable

@Override
public boolean isPoisonous() {
    return false;
}

@Override
public int getNutrition() {
    return 65;
}
  • A different capability for a different animal.

Code walkthrough 6 of 8 · Lab5Demo.java

Methods that take the abstract type or an interface

static void demonstratePolymorphism(Animal animal) {
    animal.displayInfo();
    animal.makeSound();
    animal.eat();
}

static void demonstrateDrawable(Drawable drawable) {
    drawable.draw();
    drawable.hide();
}

static void demonstrateEatable(Eatable eatable) {
    System.out.println("Poisonous : " + eatable.isPoisonous());
    System.out.println("Nutrition : " + eatable.getNutrition());
}
  • Each method accepts any object that is an Animal, a Drawable or an Eatable.

Code walkthrough 7 of 8 · Lab5Demo.java

Arrays of abstract and interface types

// 2. Polymorphism through Animal References
System.out.println("\n=== Polymorphism through Animal References ===");
Animal[] animals = {dog, bird, fish};
for (Animal animal : animals) {
    System.out.println("-------------------------------");
    demonstratePolymorphism(animal);
}

// 3. Drawable Interface
System.out.println("\n=== Drawable Interface ===");
Drawable[] drawables = {dog, bird};
for (Drawable drawable : drawables) {
    System.out.println("-------------------------------");
    demonstrateDrawable(drawable);
}
  • Animal[] holds all three; Drawable[] only Dog and Bird.

Code walkthrough 8 of 8 · Lab5Demo.java

instanceof with interfaces, then a cast

// 6. instanceof with Interfaces
System.out.println("\n=== instanceof with Interfaces ===");
System.out.println("dog instanceof Drawable  : " + (dog instanceof Drawable));
System.out.println("dog instanceof Eatable   : " + (dog instanceof Eatable));
System.out.println("fish instanceof Drawable : " + (fish instanceof Drawable));
System.out.println("fish instanceof Eatable  : " + (fish instanceof Eatable));

// 7. Safe Casting
System.out.println("\n=== Safe Casting ===");
Animal animalRef = dog;
if (animalRef instanceof Dog) {
    Dog castedDog = (Dog) animalRef;
    System.out.println("Casted Dog breed: " + castedDog.getBreed());
}
  • instanceof also answers “does this object implement Drawable?”.

Step through the code · 1 of 2

Trace: abstract methods and instanceof

One loop over an Animal[]: each object runs its own makeSound(), and only Drawable objects are drawn.

Step through the code · 1 of 2

Trace: abstract methods and instanceof (cont.)

Step through the code · 2 of 2

Trace: an abstract class still has a constructor

Animal can never be created on its own, yet its constructor runs inside every Dog.

Step through the code · 2 of 2

Trace: an abstract class still has a constructor (cont.)

For reference · 7 files

The complete program

public abstract class Animal {

    protected String name;
    protected int age;

    protected Animal(String name, int age) {
        this.name = name;
        if (age >= 0) {
            this.age = age;
        } else {
            this.age = 0;
        }
    }

    public abstract void makeSound();

    public abstract void eat();

    public String getName() { return name; }
    public int getAge() { return age; }

    public void displayInfo() {
        System.out.println("Name: " + name + ", Age: " + age + " years");
    }
}
public interface Drawable {
    void draw();
    void hide();
}
public interface Eatable {
    boolean isPoisonous();
    int getNutrition();
}
public class Dog extends Animal implements Drawable {

    private String breed;

    public Dog(String name, int age, String breed) {
        super(name, age);
        this.breed = breed;
    }

    @Override
    public void makeSound() {
        System.out.println(name + " barks: Woof! Woof!");
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating dog food from a bowl.");
    }

    @Override
    public void draw() {
        System.out.println("[Drawing] " + name + " (" + breed + ") as a dog.");
    }

    @Override
    public void hide() {
        System.out.println("[Hiding] " + name + " is no longer visible.");
    }

    public String getBreed() { return breed; }
}
public class Bird extends Animal implements Drawable {

    private double wingSpan;

    public Bird(String name, int age, double wingSpan) {
        super(name, age);
        if (wingSpan > 0.0) {
            this.wingSpan = wingSpan;
        } else {
            this.wingSpan = 0.1;
        }
    }

    @Override
    public void makeSound() {
        System.out.println(name + " chirps: Tweet! Tweet!");
    }

    @Override
    public void eat() {
        System.out.println(name + " is pecking at seeds and insects.");
    }

    @Override
    public void draw() {
        System.out.println("[Drawing] " + name + " with wingspan " + wingSpan + "m as a bird.");
    }

    @Override
    public void hide() {
        System.out.println("[Hiding] " + name + " flies away and disappears.");
    }

    public double getWingSpan() { return wingSpan; }
}
public class Fish extends Animal implements Eatable {

    private int waterDepth;

    public Fish(String name, int age, int waterDepth) {
        super(name, age);
        if (waterDepth > 0) {
            this.waterDepth = waterDepth;
        } else {
            this.waterDepth = 1;
        }
    }

    @Override
    public void makeSound() {
        System.out.println(name + " bubbles: Blub! Blub!");
    }

    @Override
    public void eat() {
        System.out.println(name + " is eating algae and small organisms.");
    }

    @Override
    public boolean isPoisonous() {
        return false;
    }

    @Override
    public int getNutrition() {
        return 65;
    }

    public int getWaterDepth() { return waterDepth; }
}
public class Lab5Demo {

    static void demonstratePolymorphism(Animal animal) {
        animal.displayInfo();
        animal.makeSound();
        animal.eat();
    }

    static void demonstrateDrawable(Drawable drawable) {
        drawable.draw();
        drawable.hide();
    }

    static void demonstrateEatable(Eatable eatable) {
        System.out.println("Poisonous : " + eatable.isPoisonous());
        System.out.println("Nutrition : " + eatable.getNutrition());
    }

    public static void main(String[] args) {

        // 1. Object Creation
        System.out.println("=== Object Creation ===");
        Dog dog = new Dog("Rex", 5, "Golden Retriever");
        Bird bird = new Bird("Tweety", 2, 0.5);
        Fish fish = new Fish("Nemo", 1, 20);
        System.out.println("Created Dog : " + dog.getName());
        System.out.println("Created Bird: " + bird.getName());
        System.out.println("Created Fish: " + fish.getName());

        // 2. Polymorphism through Animal References
        System.out.println("\n=== Polymorphism through Animal References ===");
        Animal[] animals = {dog, bird, fish};
        for (Animal animal : animals) {
            System.out.println("-------------------------------");
            demonstratePolymorphism(animal);
        }

        // 3. Drawable Interface
        System.out.println("\n=== Drawable Interface ===");
        Drawable[] drawables = {dog, bird};
        for (Drawable drawable : drawables) {
            System.out.println("-------------------------------");
            demonstrateDrawable(drawable);
        }

        // 4. Eatable Interface
        System.out.println("\n=== Eatable Interface ===");
        demonstrateEatable(fish);

        // 5. Abstract Class Instantiation Rule
        System.out.println("\n=== Abstract Class Instantiation Rule ===");
        System.out.println("Animal cannot be instantiated directly.");
        System.out.println("Use concrete subclasses such as Dog, Bird, and Fish.");

        // 6. instanceof with Interfaces
        System.out.println("\n=== instanceof with Interfaces ===");
        System.out.println("dog instanceof Drawable  : " + (dog instanceof Drawable));
        System.out.println("dog instanceof Eatable   : " + (dog instanceof Eatable));
        System.out.println("fish instanceof Drawable : " + (fish instanceof Drawable));
        System.out.println("fish instanceof Eatable  : " + (fish instanceof Eatable));

        // 7. Safe Casting
        System.out.println("\n=== Safe Casting ===");
        Animal animalRef = dog;
        if (animalRef instanceof Dog) {
            Dog castedDog = (Dog) animalRef;
            System.out.println("Casted Dog breed: " + castedDog.getBreed());
        }
    }
}

Copy or download each file, save it under the same name, then compile and run: javac *.java → java Lab5Demo

Implementation

Expected output

The same three method calls produce three different results — that is polymorphism through the abstract class.

Interactive 1 of 2

Which types does each object satisfy?

Interactive 2 of 2

One abstract method, many shapes

In-lab task 1 of 3

Task 1: Add a Cat class

A concrete Animal that is also Drawable.
Requirements
Show a hint
If you forget one abstract or interface method, the compiler tells you exactly which.

In-lab task 2 of 3

Task 2: Create a Trainable interface

A capability shared by Dog and Cat.
Requirements
Show a hint
class Dog extends Animal implements Drawable, Trainable

In-lab task 3 of 3

Task 3: Interface-based parameters

Write feedAnimal(Eatable eatable).
Requirements
Show a hint
The parameter type is the contract: only objects whose class implements Eatable can be passed.

In-lab tasks

Show your work during the lab

For each task, show the instructor:

  • the source code
  • a successful compilation
  • the running output
  • a short explanation of the logic you used

Lab report · exercise 1 of 2

Shape hierarchy with multiple interfaces

Abstract Shape with Resizable and Colorable interfaces.
Requirements

Lab report · exercise 2 of 2

Employee management with role interfaces

Abstract Employee with Payable and Evaluable.
Requirements

Lab report

Writing the lab report

  • Problem statement and your design (classes, fields, methods)
  • Complete source code, formatted and commented
  • Sample output or screenshots for normal and edge cases
  • A short discussion: what each OOP concept did in your program

Academic integrity

Copying from the internet, classmates, seniors or any other unauthorized source is strictly prohibited. Full marks may be deducted if plagiarism, copied work or academic dishonesty is detected. Complete the tasks, implementation, output analysis and report yourself.

Discussion and analysis

Viva questions (1 of 2)

Why is Animal abstract instead of a normal class?
Show the answer
There is no meaningful generic animal sound or diet; making it abstract forbids plain Animal objects and forces every subclass to provide them.
Can an abstract class have a constructor?
Show the answer
Yes. It initialises the shared fields and is called from subclass constructors with super(…).

Discussion and analysis

Viva questions (2 of 2)

Why are Drawable and Eatable interfaces and not abstract classes?
Show the answer
They are capabilities that only some animals have, and a class can implement several interfaces but extend only one class.
fish instanceof Drawable is false. Why does it still compile?
Show the answer
instanceof is checked at run time against the object; the compiler allows it because some Animal subclass could be Drawable.

Check yourself

Quiz

Summary

Summary

  • Abstract classes share state and code and force subclasses to implement abstract methods.
  • They cannot be instantiated but can have constructors.
  • Interfaces are contracts; a class can implement many.
  • Use abstract classes for is-a, interfaces for can-do.
  • Both work as reference types for polymorphism; instanceof checks interfaces too.