Defining Subclasses

Introduction

Defining a subclass means creating a new class that inherits from an existing class using the extends keyword.


Syntax

class Subclass extends Superclass {
    // Additional fields
    // Additional methods
    // Overridden methods
}

Basic Example

// Superclass
class Employee {
    String name;
    double salary;

    void work() {
        System.out.println(name + " is working");
    }
}

// Subclass
class Manager extends Employee {
    String department;

    void manage() {
        System.out.println(name + " is managing " + department);
    }
}

public class Main {
    public static void main(String[] args) {
        Manager m = new Manager();
        m.name = "John";           // Inherited
        m.salary = 80000;          // Inherited
        m.department = "IT";       // Own field

        m.work();    // Inherited method
        m.manage();  // Own method
    }
}

Adding Fields

class Vehicle {
    String brand;
    int year;
}

class Car extends Vehicle {
    // Add new fields
    int doors;
    String fuelType;
    boolean isAutomatic;

    void displayInfo() {
        System.out.println("Brand: " + brand);        // Inherited
        System.out.println("Year: " + year);          // Inherited
        System.out.println("Doors: " + doors);        // Own
        System.out.println("Fuel: " + fuelType);      // Own
        System.out.println("Automatic: " + isAutomatic); // Own
    }
}

Adding Methods

class Shape {
    String color;

    void display() {
        System.out.println("Color: " + color);
    }
}

class Circle extends Shape {
    double radius;

    // Add new method
    double area() {
        return Math.PI * radius * radius;
    }

    // Add new method
    double circumference() {
        return 2 * Math.PI * radius;
    }
}

public class Main {
    public static void main(String[] args) {
        Circle c = new Circle();
        c.color = "Red";
        c.radius = 5.0;

        c.display();  // Inherited
        System.out.println("Area: " + c.area());
        System.out.println("Circumference: " + c.circumference());
    }
}

Complete Example

// Superclass
class BankAccount {
    protected String accountNumber;
    protected String holderName;
    protected double balance;

    void deposit(double amount) {
        balance += amount;
        System.out.println("Deposited: " + amount);
    }

    void displayBalance() {
        System.out.println("Balance: " + balance);
    }
}

// Subclass
class SavingsAccount extends BankAccount {
    private double interestRate;

    // Constructor
    SavingsAccount(String accountNumber, String holderName, double interestRate) {
        this.accountNumber = accountNumber;
        this.holderName = holderName;
        this.interestRate = interestRate;
        this.balance = 0;
    }

    // New method
    void addInterest() {
        double interest = balance * interestRate / 100;
        balance += interest;
        System.out.println("Interest added: " + interest);
    }

    // New method
    void displayDetails() {
        System.out.println("Account: " + accountNumber);
        System.out.println("Holder: " + holderName);
        System.out.println("Interest Rate: " + interestRate + "%");
        displayBalance();  // Call inherited method
    }
}

public class Main {
    public static void main(String[] args) {
        SavingsAccount acc = new SavingsAccount("SA1001", "John", 4.5);

        acc.deposit(10000);      // Inherited method
        acc.addInterest();       // Own method
        acc.displayDetails();    // Own method
    }
}

Using super Keyword

Accessing Parent Fields:

class Parent {
    int x = 10;
}

class Child extends Parent {
    int x = 20;  // Hides parent's x

    void display() {
        System.out.println("Child x: " + x);        // 20
        System.out.println("Parent x: " + super.x); // 10
    }
}

Calling Parent Methods:

class Parent {
    void display() {
        System.out.println("Parent display");
    }
}

class Child extends Parent {
    void display() {
        super.display();  // Call parent method
        System.out.println("Child display");
    }
}

Constructor in Subclass

class Parent {
    String name;

    Parent(String name) {
        this.name = name;
        System.out.println("Parent constructor");
    }
}

class Child extends Parent {
    int age;

    Child(String name, int age) {
        super(name);  // Call parent constructor
        this.age = age;
        System.out.println("Child constructor");
    }

    void display() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child("John", 20);
        c.display();
    }
}

Output:

Parent constructor
Child constructor
Name: John
Age: 20

Access Modifiers in Subclass

class Parent {
    public int publicVar = 10;
    protected int protectedVar = 20;
    int defaultVar = 30;           // Package-private
    private int privateVar = 40;
}

class Child extends Parent {
    void display() {
        System.out.println(publicVar);      // ✓ Accessible
        System.out.println(protectedVar);   // ✓ Accessible
        System.out.println(defaultVar);     // ✓ Accessible (same package)
        // System.out.println(privateVar);  // ✗ Not accessible
    }
}

Multilevel Subclass

class GrandParent {
    void method1() {
        System.out.println("GrandParent method");
    }
}

class Parent extends GrandParent {
    void method2() {
        System.out.println("Parent method");
    }
}

class Child extends Parent {
    void method3() {
        System.out.println("Child method");
    }

    void callAll() {
        method1();  // From GrandParent
        method2();  // From Parent
        method3();  // Own method
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child();
        c.callAll();
    }
}

Real-World Example

// Superclass
class Person {
    protected String name;
    protected int age;
    protected String address;

    Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    void displayInfo() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Address: " + address);
    }
}

// Subclass 1
class Student extends Person {
    private int rollNo;
    private String course;
    private double marks;

    Student(String name, int age, String address, int rollNo, String course) {
        super(name, age, address);
        this.rollNo = rollNo;
        this.course = course;
    }

    void setMarks(double marks) {
        this.marks = marks;
    }

    void displayStudent() {
        displayInfo();  // Call parent method
        System.out.println("Roll No: " + rollNo);
        System.out.println("Course: " + course);
        System.out.println("Marks: " + marks);
    }
}

// Subclass 2
class Teacher extends Person {
    private String employeeId;
    private String subject;
    private double salary;

    Teacher(String name, int age, String address, String employeeId, String subject) {
        super(name, age, address);
        this.employeeId = employeeId;
        this.subject = subject;
    }

    void setSalary(double salary) {
        this.salary = salary;
    }

    void displayTeacher() {
        displayInfo();  // Call parent method
        System.out.println("Employee ID: " + employeeId);
        System.out.println("Subject: " + subject);
        System.out.println("Salary: " + salary);
    }
}

public class Main {
    public static void main(String[] args) {
        Student s = new Student("John", 20, "123 Street", 101, "BCA");
        s.setMarks(85.5);
        s.displayStudent();

        System.out.println();

        Teacher t = new Teacher("Alice", 35, "456 Avenue", "T001", "Java");
        t.setSalary(50000);
        t.displayTeacher();
    }
}

Rules for Defining Subclass

  1. Use extends keyword
  2. Can extend only one class (single inheritance)
  3. Can add new fields and methods
  4. Can override parent methods
  5. Cannot access private members of parent
  6. Must call super() if parent has parameterized constructor
  7. Constructor not inherited
  8. Can use super to access parent members

Method Overriding in Subclass

class Parent {
    void display() {
        System.out.println("Parent display");
    }
}

class Child extends Parent {
    @Override
    void display() {  // Override parent method
        System.out.println("Child display");
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child();
        c.display();  // Calls Child's version
    }
}

Quick Reference

// Define subclass
class Subclass extends Superclass {
    // Additional fields
    int newField;

    // Constructor
    Subclass() {
        super();  // Call parent constructor
    }

    // Additional methods
    void newMethod() { }

    // Override parent method
    @Override
    void parentMethod() {
        super.parentMethod();  // Call parent version
        // Additional code
    }
}

Exam Tips

Remember:

  1. Use extends to define subclass
  2. Subclass inherits non-private members
  3. Can add new fields and methods
  4. Use super to access parent members
  5. super() calls parent constructor
  6. super() must be first in constructor
  7. Can override parent methods
  8. Use @Override annotation
  9. Cannot access private parent members
  10. protected members accessible in subclass

Common Questions:

  • How to define subclass?
  • What does extends do?
  • What is super keyword?
  • How to call parent constructor?
  • Can subclass add new methods?
  • What is method overriding?
  • Which members are inherited?
  • Rules for defining subclass?