Back to Week 9
Lab Session

Week 9: Lab — Abstract Classes & Interfaces

Hands-on Programming Exercises — Ch. 13

Progress0 / 6 completed

1Abstract Class — GeometricObject

Think about it: Every shape has an area and a perimeter, but the formula differs between a circle and a rectangle. An abstract class lets you define this contract — "every GeometricObject must have getArea() and getPerimeter()" — without providing the formula. Each concrete subclass then fills in the calculation for its own shape.
Create an abstract class GeometricObject with fields color (String) and filled (boolean), a constructor, getters/setters, and two abstract methods: getArea() and getPerimeter(). Create concrete class Circle (field: radius) and Rectangle (fields: width, height) that extend it and implement both abstract methods. In main, create one of each and print their properties.
Expected OutputCircle — color: red, filled: true Area: 78.53981633974483 Perimeter: 31.41592653589793 Rectangle — color: blue, filled: false Area: 24.0 Perimeter: 20.0
Your Code
Abstract class: abstract class GeometricObject { String color; boolean filled; GeometricObject(String color, boolean filled){...} public abstract double getArea(); public abstract double getPerimeter(); }. Circle: class Circle extends GeometricObject { double radius; Circle(double radius, String color, boolean filled){ super(color, filled); this.radius = radius; } public double getArea(){ return Math.PI * radius * radius; } public double getPerimeter(){ return 2 * Math.PI * radius; } }. Rectangle follows the same pattern with width * height and 2*(width+height).

2Abstract Methods — Animal Sounds

Think about it: All animals breathe — that behavior is shared and can be defined in the abstract class. But how each animal makes a sound is different. Making makeSound() abstract forces every concrete subclass to provide its own sound implementation. This is the core power of abstract methods: enforce a contract without dictating the implementation.
Create an abstract class Animal with a field name (String), a constructor, an abstract method makeSound(), and a concrete method breathe() that prints "[name] is breathing". Create three concrete subclasses: Dog (prints "Woof!"), Cat (prints "Meow!"), and Bird (prints "Tweet!"). In main, create an array of Animal references and call both methods on each.
Expected OutputRex is breathing Rex says: Woof! Whiskers is breathing Whiskers says: Meow! Tweety is breathing Tweety says: Tweet!
Your Code
Abstract Animal: abstract class Animal { String name; Animal(String name){ this.name = name; } public abstract void makeSound(); public void breathe(){ System.out.println(name + " is breathing"); } }. Dog: class Dog extends Animal { Dog(String name){ super(name); } public void makeSound(){ System.out.println(name + " says: Woof!"); } }. Cat and Bird follow the same pattern with "Meow!" and "Tweet!" respectively.

3Interface — Drawable & Resizable

Think about it: A Square and a Triangle are unrelated shapes, but both can be drawn and resized. Interfaces let unrelated classes share a common capability without forcing an inheritance hierarchy. A class can implement multiple interfaces, which is impossible with abstract class inheritance.
Create interface Drawable with method draw(). Create interface Resizable with method resize(double factor). Create class Square with field side (double) that implements both interfaces: draw() prints the side length and resize(factor) multiplies side by factor. Create class Triangle with field base (double) that also implements both. In main, demonstrate both.
Expected OutputDrawing Square with side: 4.0 Resizing Square by factor 2.0 → new side: 8.0 Drawing Triangle with base: 3.0 Resizing Triangle by factor 1.5 → new base: 4.5
Your Code
Interface: interface Drawable { void draw(); } — all methods are implicitly public abstract. Implementing both: class Square implements Drawable, Resizable { double side; Square(double side){ this.side = side; } public void draw(){ System.out.println("Drawing Square with side: " + side); } public void resize(double factor){ side *= factor; System.out.println("Resizing Square by factor " + factor + " \u2192 new side: " + side); } }. Triangle follows the same pattern with base.

4Comparable Interface — Student Sorting

Think about it: How does Arrays.sort() know how to order your objects? It doesn't — unless your class implements Comparable and defines a compareTo() method. Implementing Comparable<T> gives your class a natural ordering that Java's built-in sort methods can use automatically.
Create a Student class that implements Comparable<Student>. Fields: name (String) and gpa (double). Implement compareTo(Student other) to sort by GPA in ascending order (return negative if this GPA < other GPA, positive if greater, zero if equal). Use Double.compare(this.gpa, other.gpa). In main, create an array of students, sort with Arrays.sort(), and print them.
Expected Output--- Sorted by GPA (ascending) --- Omar: 3.1 Ali: 3.5 Lina: 3.7 Sara: 3.9
Your Code
class Student implements Comparable<Student>. The compareTo method: public int compareTo(Student other) { return Double.compare(this.gpa, other.gpa); } — returns negative when this < other, zero when equal, positive when this > other. toString(): public String toString() { return name + ": " + gpa; }. Then Arrays.sort(students) will automatically use your compareTo.

5Multiple Interfaces — Flyable & Swimmable

Think about it: A Duck can both fly and swim — two capabilities that come from completely different domains. In Java, a class can only extend one abstract class, but it can implement multiple interfaces. This is the key advantage of interfaces when modeling unrelated capabilities that can be combined.
Create interface Flyable with method fly(). Create interface Swimmable with method swim(). Create class Duck that implements both: fly() prints "Duck is flying", swim() prints "Duck is swimming". Create class Eagle that implements only Flyable: prints "Eagle is soaring". Create class Fish that implements only Swimmable: prints "Fish is swimming". In main, demonstrate each using interface references.
Expected OutputDuck is flying Duck is swimming Eagle is soaring Fish is swimming
Your Code
Interface declaration: interface Flyable { void fly(); }. Implementing multiple: class Duck implements Flyable, Swimmable { public void fly(){ System.out.println("Duck is flying"); } public void swim(){ System.out.println("Duck is swimming"); } }. Notice Flyable eagle = new Eagle() — an interface reference can hold any object that implements it. This enables polymorphism through interfaces.

6Abstract Class + Interface — ElectricCar

Think about it: An ElectricCar is a Vehicle (abstract class — shared state and behavior) and can be charged (interface — additional capability). This is the key design rule: use an abstract class for an "is-a" relationship where subclasses share code, and an interface for a "can-do" capability that unrelated classes might share.
Create an abstract class Vehicle with field brand (String), a constructor, a concrete method startEngine() that prints "Starting [brand] engine", and an abstract method drive(). Create interface Electric with method charge(). Create class ElectricCar that extends Vehicle and implements Electric: drive() prints "Driving silently", charge() prints "Charging battery". Create class GasCar that extends Vehicle only: drive() prints "Driving with engine roar".
Expected OutputStarting Tesla engine Driving silently Charging battery Starting Toyota engine Driving with engine roar
Your Code
Abstract Vehicle: abstract class Vehicle { String brand; Vehicle(String brand){ this.brand = brand; } public void startEngine(){ System.out.println("Starting " + brand + " engine"); } public abstract void drive(); }. Electric interface: interface Electric { void charge(); }. ElectricCar: class ElectricCar extends Vehicle implements Electric { ElectricCar(String brand){ super(brand); } public void drive(){ System.out.println("Driving silently"); } public void charge(){ System.out.println("Charging battery"); } }. Key: a class can extends one class AND implements one or more interfaces simultaneously.