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
- Theory recap
- Walk through the program, section by section, and run it
- In-lab tasks, shown to the instructor
- Report exercises at home
Lab 5 of 10
Contents
Select a part to jump to it.
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 class | Interface | |
|---|---|---|
| Relationship | is-a (Dog is an Animal) | can-do (Dog can be drawn) |
| State | fields and constructors | constants only |
| Inheritance | extend one | implement many |
| Use when | related classes share code | unrelated 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().
instanceofworks with interfaces too.
Implementation design
Execution flow
- Create a Dog, a Bird and a Fish
- Loop over an Animal[]: displayInfo(), makeSound(), eat()
- Loop over a Drawable[]: draw(), hide()
- Use the Fish through an Eatable reference
- Show that Animal cannot be instantiated
- Test instanceof with both interfaces
- 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
=== Object Creation === Created Dog : Rex Created Bird: Tweety Created Fish: Nemo === Polymorphism through Animal References === ------------------------------- Name: Rex, Age: 5 years Rex barks: Woof! Woof! Rex is eating dog food from a bowl. ------------------------------- Name: Tweety, Age: 2 years Tweety chirps: Tweet! Tweet! Tweety is pecking at seeds and insects. ------------------------------- Name: Nemo, Age: 1 years Nemo bubbles: Blub! Blub! Nemo is eating algae and small organisms. === Drawable Interface === ------------------------------- [Drawing] Rex (Golden Retriever) as a dog. [Hiding] Rex is no longer visible. ------------------------------- [Drawing] Tweety with wingspan 0.5m as a bird. [Hiding] Tweety flies away and disappears. === Eatable Interface === Poisonous : false Nutrition : 65 === Abstract Class Instantiation Rule === Animal cannot be instantiated directly. Use concrete subclasses such as Dog, Bird, and Fish. === instanceof with Interfaces === dog instanceof Drawable : true dog instanceof Eatable : false fish instanceof Drawable : false fish instanceof Eatable : true === Safe Casting === Casted Dog breed: Golden Retriever
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
Show a hint
In-lab task 2 of 3
Task 2: Create a Trainable interface
Show a hint
class Dog extends Animal implements Drawable, TrainableIn-lab task 3 of 3
Task 3: Interface-based parameters
feedAnimal(Eatable eatable).Show a hint
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
Lab report · exercise 2 of 2
Employee management with role interfaces
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)
Show the answer
Show the answer
Discussion and analysis
Viva questions (2 of 2)
Show the answer
fish instanceof Drawable is false. Why does it still compile?Show the answer
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.