Object Oriented Programming with JavaUnit 119 min read
Polymorphism, Abstraction, Sealed Classes & Design Patterns
Unit 11 of Object Oriented Programming with Java explores polymorphism (compile-time vs. runtime), abstraction (interfaces vs. abstract classes), sealed hierarchies, and design patterns (Singleton, Factory, Observer) with real-world Java examples and implementation traces.
Key Concepts and Definitions
1. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common superclass. It is divided into two types:
1.1 Compile-Time Polymorphism (Method Overloading)
- Same method name, different parameters (type, number, or order).
- Resolved during compilation.
- Example:
add(int a, int b)andadd(double a, double b).
1.2 Runtime Polymorphism (Method Overriding)
- Same method signature in superclass and subclass.
- Resolved during runtime using dynamic method dispatch.
- Example:
Animalclass withsound()overridden inDogandCat.
class Animal {
void sound() { System.out.println("Animal sound"); }
}
class Dog extends Animal {
@Override
void sound() { System.out.println("Bark"); }
}
class Cat extends Animal {
@Override
void sound() { System.out.println("Meow"); }
}
Trace:
| Step | Object Type | Method Called |
|---|---|---|
| 1 | Animal a = new Dog() |
Dog.sound() |
| 2 | Animal c = new Cat() |
Cat.sound() |
2. Abstraction
Abstraction hides implementation details and shows only essential features.
classDiagram
class Shape {
<<abstract>>
+area() double
}
class Circle {
-radius double
+area() double
}
class Rectangle {
-length double
-width double
+area() double
}
Shape <|-- Circle
Shape <|-- RectangleAbstract Shape hierarchy with concrete implementations2.1 Abstract Classes
- Cannot be instantiated.
- Can have abstract and concrete methods.
- Use
abstractkeyword. - Example:
Shapewith abstractarea()method.
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
double radius;
Circle(double r) { radius = r; }
@Override
double area() { return Math.PI * radius * radius; }
}
2.2 Interfaces
- Fully abstract (all methods are
public abstractby default). - Can have
defaultandstaticmethods (Java 8+). - A class can implement multiple interfaces.
- Example:
Drawableinterface for shapes.
interface Drawable {
void draw();
default void display() { System.out.println("Drawing..."); }
}
class Rectangle implements Drawable {
@Override
public void draw() { System.out.println("Drawing Rectangle"); }
}
Comparison Table:
| Feature | Abstract Class | Interface |
|---|---|---|
| Instantiation | No | No |
| Abstract Methods | Yes | Yes (default in Java 8+) |
| Concrete Methods | Yes | Yes (default/static) |
| Fields | Yes (non-final) | No (only public static final) |
| Multiple Inheritance | No | Yes (multiple interfaces) |
extends/implements |
extends |
implements |
3. Sealed Classes (Java 17+)
- Restrict which classes can extend or implement them.
- Improves type safety and documentation.
- Example: Sealed hierarchy for
PaymentMethod.
sealed interface PaymentMethod permits CreditCard, DebitCard, UPI {
void processPayment(double amount);
}
final class CreditCard implements PaymentMethod {
@Override
public void processPayment(double amount) { /* ... */ }
}
non-sealed class DebitCard implements PaymentMethod {
@Override
public void processPayment(double amount) { /* ... */ }
}
Visualization:
classDiagram
class PaymentMethod {
<<sealed>>
+processPayment(amount: double)
+finalize() void
}
class CreditCard {
+processPayment(amount: double)
}
class DebitCard {
+processPayment(amount: double)
}
class UPI {
+processPayment(amount: double)
}
PaymentMethod <|-- CreditCard
PaymentMethod <|-- DebitCard
PaymentMethod <|-- UPI
note for PaymentMethod "sealed permits only CreditCard, DebitCard, UPI"4. Design Patterns
Design patterns are reusable solutions to common problems.
4.1 Singleton Pattern
- Ensures a class has only one instance.
- Used in logging, database connections.
- Example:
DatabaseConnection.
class DatabaseConnection {
private static DatabaseConnection instance;
private DatabaseConnection() {}
public static DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
}
Thread-Safe Singleton (Double-Checked Locking):
public static DatabaseConnection getInstance() {
if (instance == null) {
synchronized (DatabaseConnection.class) {
if (instance == null) {
instance = new DatabaseConnection();
}
}
}
return instance;
}
4.2 Factory Pattern
- Creates objects without specifying the exact class.
- Example:
VehicleFactoryforCarandBike.
interface Vehicle {
void drive();
}
class Car implements Vehicle { public void drive() { System.out.println("Driving Car"); } }
class Bike implements Vehicle { public void drive() { System.out.println("Riding Bike"); } }
class VehicleFactory {
public Vehicle getVehicle(String type) {
if (type.equals("car")) return new Car();
else if (type.equals("bike")) return new Bike();
throw new IllegalArgumentException("Invalid vehicle type");
}
}
4.3 Observer Pattern
- Notifies observers when an event occurs.
- Example:
NewsAgencyandJournalists.
interface Observer {
void update(String news);
}
class NewsAgency {
private List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) { observers.add(o); }
public void notifyObservers(String news) {
for (Observer o : observers) o.update(news);
}
}
class Journalist implements Observer {
@Override
public void update(String news) { System.out.println("Journalist received: " + news); }
}
In the Real World
- Khalti (Nepal) uses the Singleton Pattern for its
PaymentGatewayclass to ensure only one instance manages transactions, preventing duplicate payments. - Daraz (Nepal) employs the Factory Pattern in its order processing system to create different order types (
PhysicalOrder,DigitalOrder) dynamically. - Ncell (Nepal) leverages Observer Pattern to notify users about promotions or balance updates via SMS/email.
Worked Example:
- Bank Loan Interest Calculation (Polymorphism):
Suppose a bank has
Loan(abstract) withcalculateInterest(), overridden inHomeLoanandCarLoan.
Trace:abstract class Loan { abstract double calculateInterest(double principal, int years); } class HomeLoan extends Loan { @Override double calculateInterest(double p, int y) { return p * 0.08 * y; } } class CarLoan extends Loan { @Override double calculateInterest(double p, int y) { return p * 0.12 * y; } }Loan Type Principal (Rs.) Years Interest (Rs.) HomeLoan 5,000,000 10 400,000 CarLoan 2,000,000 5 1,200,000
Exam Tip
- Polymorphism: Focus on method overriding (runtime) vs. overloading (compile-time). Always trace object types and method calls.
- Abstraction: Differentiate between abstract classes (partial abstraction) and interfaces (full abstraction). Remember
defaultmethods in interfaces. - Sealed Classes: Know the
permitsclause and how it restricts inheritance. - Design Patterns: Be ready to write code for Singleton, Factory, and Observer. Explain their use cases (e.g., Singleton for logging, Factory for object creation).
- Common Pitfalls:
- Forgetting
@Overrideannotation. - Misusing
staticmethods in interfaces. - Thread-safety issues in Singleton (use
synchronizedorenum).
- Forgetting
Visual Summary:
Based on the TU BIM syllabus for Object Oriented Programming with Java (IT234), unit 11.
Discussion
Loading…