ISC Computer Science · Class XII

Inheritance,
Interfaces &
Polymorphism

The complete theory guide — every concept explained, every exam pattern covered. Let's get 100/100.

Super & Derived Classes Member Access Abstract Classes Polymorphism Interfaces
01

Inheritance — The Foundation

Inheritance is the mechanism by which one class acquires all the properties and behaviours of another class. It is Java's primary tool for code reuse and establishing a genuine IS-A relationship between classes.

Definition — Inheritance
Inheritance is the process by which a new class (subclass/derived class) is created from an existing class (superclass/base class), automatically acquiring all its non-private fields and methods. The keyword used is extends.

🏛️ Superclass (Parent / Base)

The existing class whose properties are being inherited. Also called parent class or base class. Defines the common attributes and behaviours shared by all subclasses.

🌿 Subclass (Child / Derived)

The new class that inherits from the superclass. Also called child class or derived class. It extends the superclass and can add its own attributes and methods, or override existing ones.

⚠️
ISC Emphasis — When to Use Inheritance

Inheritance should ONLY be used when there is a genuine IS-A relationship. A Dog IS-A Animal ✅. A Car IS-A Vehicle ✅. Do NOT use inheritance simply to reuse a few methods — that is a design mistake. Use composition (HAS-A) for code reuse without a true specialization relationship.

Superclass
Animal
name, age
eat(), sleep(), breathe()
Subclass
Dog
breed
bark(), fetch()
Sub-subclass
GoldenRetriever
coatColor
retrieveItem()
Subclass
Cat
isIndoor
purr(), climb()
Subclass
Bird
wingspan
fly(), sing()

Types of Inheritance in Java

TypeDescriptionSupported in Java?
SingleOne class inherits from exactly one superclass✅ Yes
MultilevelChain: A → B → C (B inherits A, C inherits B)✅ Yes
HierarchicalMultiple classes inherit from one superclass✅ Yes
MultipleOne class inherits from two or more classes❌ Not via classes ✅ Via interfaces
HybridCombination of the above types⚠️ Partial via interfaces
Animal.java — Single Inheritance Java
// SUPERCLASS
class Animal {
    String name;
    int    age;

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

    void eat()    { System.out.println(name + " is eating."); }
    void breathe(){ System.out.println(name + " is breathing."); }
}

// SUBCLASS — inherits from Animal using 'extends'
class Dog extends Animal {
    String breed;  // new attribute specific to Dog

    Dog(String name, int age, String breed) {
        super(name, age);  // call superclass constructor
        this.breed = breed;
    }

    void bark() {          // new method specific to Dog
        System.out.println(name + " says: Woof!");
    }
}

class Main {
    public static void main(String[] args) {
        Dog d = new Dog("Bruno", 3, "Labrador");
        d.eat();    // inherited from Animal → "Bruno is eating."
        d.breathe(); // inherited               → "Bruno is breathing."
        d.bark();   // own method             → "Bruno says: Woof!"
        System.out.println("Breed: " + d.breed);
        System.out.println("Age:   " + d.age);   // inherited field
    }
}
⭐ Exam Tips — Inheritance Basics
  • IS-A test: Before using extends, ask — is a Dog an Animal? Yes ✅. Is an Engine a Car? No ❌ (it HAS a car → use composition).
  • Java does NOT support multiple inheritance through classes — to avoid the "Diamond Problem".
  • A subclass inherits all members EXCEPT: private members (accessible via getters), constructors (not inherited), static members (shared but not inherited per se).
  • The keyword is extends for classes, implements for interfaces.
02

The super Keyword

super is a reference variable that refers to the immediate parent class object. It is used in three key ways — calling the parent constructor, accessing parent methods, and accessing parent variables.

① super() — Constructor Call

Calls the superclass constructor. Must be the FIRST statement in the subclass constructor. Used to initialise the inherited portion of the object.

② super.method() — Method Call

Calls a method of the superclass that has been overridden in the subclass. Allows you to extend superclass behaviour rather than replace it entirely.

③ super.variable — Field Access

Accesses a variable of the superclass when the subclass defines a variable with the same name (variable hiding/shadowing).

super — All Three Uses Java
class Shape {
    String color;

    Shape(String color) {
        this.color = color;
        System.out.println("Shape constructor: color = " + color);
    }

    void draw() {
        System.out.println("Drawing a " + color + " shape");
    }
}

class Circle extends Shape {
    double radius;
    String color; // shadows Shape.color → variable hiding

    Circle(String color, double radius) {
        super(color);          // ① calls Shape(color) — MUST be first!
        this.radius = radius;
        this.color  = "Bright " + color; // subclass color
    }

    void draw() {             // overrides Shape.draw()
        super.draw();          // ② calls superclass draw() first
        System.out.println("Drawing circle of radius " + radius);
    }

    void showColors() {
        System.out.println("Subclass color : " + this.color);
        System.out.println("Superclass color: " + super.color); // ③ parent field
    }
}

class Main {
    public static void main(String[] args) {
        Circle c = new Circle("Red", 5.0);
        c.draw();
        c.showColors();
    }
}
⚠️
super() vs this() — Critical Difference

super() calls the superclass constructor; this() calls another constructor in the same class. Both must be the FIRST statement in a constructor — so they CANNOT both appear in the same constructor.

UsageSyntaxPurpose
Constructor callsuper(args)Invoke parent class constructor — must be first line
Method callsuper.methodName()Call overridden parent method from subclass
Field accesssuper.fieldNameAccess parent field when subclass field has same name
03

Member Access in Derived Classes & protected Visibility

Not all members of a superclass are directly accessible in a subclass. Java's access modifiers control exactly which members are visible and where.

Modifier Same Class Same Package Subclass (diff. pkg) Any Other Class
private
default (no modifier)
protected KEY FOR INHERITANCE
public
protected Visibility
protected members are accessible within the same package AND in any subclass (even from a different package). It is designed specifically for inheritance — giving subclasses access to superclass internals without making them fully public. This is the recommended access level for fields intended to be used by subclasses.
Access Modifiers in Inheritance Java
class Vehicle {
    private   String chassisNo;  // NOT accessible in subclass directly
    protected String brand;       // accessible in subclass ✅
    protected int    speed;       // accessible in subclass ✅
    public    String type;        // accessible everywhere ✅

    protected void startEngine() {
        System.out.println(brand + " engine started.");
    }

    private String getChassis() {  // can be called by Vehicle only
        return chassisNo;
    }
}

class Car extends Vehicle {
    int doors;

    Car(String brand, int speed, int doors) {
        this.brand = brand;   // ✅ protected — accessible here
        this.speed = speed;   // ✅ protected
        this.doors = doors;
        // this.chassisNo = "..."; ← ❌ COMPILE ERROR — private
    }

    void details() {
        startEngine();        // ✅ protected method — accessible
        System.out.println("Brand: " + brand + "  Doors: " + doors);
    }
}
⭐ Exam Tips — Member Access
  • private members are NEVER directly inherited — but they ARE present in the subclass object in memory; they are just not accessible directly. Use getters/setters.
  • protected is the bridge — it's the right choice for fields you want subclasses to use without exposing to the world.
  • Constructors are NEVER inherited regardless of access modifier.
04

Method Overriding & Variable Redefinition

A subclass can redefine (override) methods and variables inherited from its superclass to provide a specific implementation for its own type.

Method Overriding
When a subclass provides its own implementation of a method that is already defined in its superclass — with the same name, same return type, and same parameter list — it is called method overriding. The subclass version replaces (overrides) the parent version for objects of the subclass type.
Method Overriding Java
class Employee {
    String name;
    double basicSalary;

    Employee(String name, double basic) {
        this.name        = name;
        this.basicSalary = basic;
    }

    double calculateBonus() {
        return basicSalary * 0.10; // 10% bonus for all employees
    }

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

// Manager IS-A Employee (specialisation)
class Manager extends Employee {
    int teamSize;

    Manager(String name, double basic, int teamSize) {
        super(name, basic);
        this.teamSize = teamSize;
    }

    @Override
    double calculateBonus() {         // OVERRIDES Employee.calculateBonus()
        return basicSalary * 0.20      // 20% base bonus
             + teamSize * 1000;       // extra per team member
    }
}

class Main {
    public static void main(String[] args) {
        Employee e = new Employee("Aarav", 30000);
        Manager  m = new Manager("Priya", 50000, 8);

        e.display();   // bonus = 3000   (Employee version)
        m.display();   // bonus = 18000  (Manager version — overridden)
    }
}

Overriding vs Overloading

FeatureMethod OverridingMethod Overloading
ClassTwo different classes (parent & child)Same class
SignatureSame name, same parameters, same return typeSame name, different parameters
Resolved atRuntime (dynamic binding)Compile time (static binding)
Keyword@Override (annotation, recommended)No special keyword
PurposeChange inherited behaviour for a subtypeMultiple versions of same task
PolymorphismRuntime polymorphismCompile-time polymorphism
🚫
Rules for Method Overriding

The overriding method CANNOT have more restrictive access (e.g., if parent is public, child cannot be private). You CANNOT override final methods, static methods (that's method hiding, not overriding), or constructors. The @Override annotation is optional but strongly recommended — it catches errors at compile time.

🔢
Variable Hiding (Redefinition of Variables)

If a subclass declares a variable with the same name as a superclass variable, the superclass variable is hidden (not overridden). The subclass variable shadows the parent's. Use super.varName to access the parent's version. Unlike method overriding, variable resolution is based on the reference type (compile time), not the object type.

05

Abstract Classes

Sometimes a superclass is so general that it doesn't make sense to create objects directly from it. Abstract classes enforce a contract — subclasses MUST provide the implementation.

Definition — Abstract Class
An abstract class is a class declared with the abstract keyword. It cannot be instantiated (you cannot create objects of it directly). It may contain abstract methods (methods without a body — only signature) that MUST be overridden in non-abstract subclasses.
Definition — Abstract Method
An abstract method is a method declared with abstract and has no body — only a method signature ending with a semicolon. Any class containing at least one abstract method MUST itself be declared abstract.
Abstract Class — Shape Example Java
// ABSTRACT CLASS — cannot instantiate directly
abstract class Shape {
    String color;

    Shape(String color) {
        this.color = color;
    }

    // ABSTRACT METHODS — no body, must be overridden
    abstract double area();
    abstract double perimeter();

    // CONCRETE METHOD — has a body, inherited as-is
    void display() {
        System.out.println("Color: " + color
            + "  Area: " + area()
            + "  Perimeter: " + perimeter());
    }
}

// Concrete subclass — MUST implement all abstract methods
class Circle extends Shape {
    double radius;

    Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    @Override
    double area()      { return Math.PI * radius * radius; }

    @Override
    double perimeter() { return 2 * Math.PI * radius; }
}

// Another concrete subclass
class Rectangle extends Shape {
    double length, width;

    Rectangle(String color, double l, double w) {
        super(color);
        this.length = l; this.width = w;
    }

    @Override
    double area()      { return length * width; }

    @Override
    double perimeter() { return 2 * (length + width); }
}

class Main {
    public static void main(String[] args) {
        // Shape s = new Shape("Red"); ← ❌ COMPILE ERROR: cannot instantiate abstract
        Shape c = new Circle("Blue", 5.0);     // ✅ polymorphic reference
        Shape r = new Rectangle("Red", 4.0, 6.0); // ✅
        c.display();
        r.display();
    }
}
FeatureAbstract ClassConcrete Class
Instantiation❌ Cannot create objects✅ Can create objects
Abstract methodsCan have (0 or more)Cannot have
Concrete methodsCan haveCan have
ConstructorCan have (called via super())Can have
Subclass obligationMust implement all abstract methodsNo obligation
⭐ Exam Tips — Abstract Classes
  • Abstract class CAN have constructors — called indirectly via super() from subclass.
  • If a subclass does NOT implement all abstract methods, it must also be declared abstract.
  • An abstract class can have zero abstract methods — that's valid (prevents instantiation without forcing override).
  • abstract + final is illegal — final prevents subclassing, abstract requires it.
  • abstract + static for a method is also illegal.
06

The Object Class

Every class in Java implicitly extends java.lang.Object. This is the root of the entire Java class hierarchy — every object you ever create is ultimately an instance of Object.

java.lang.Object
Object is the ultimate superclass of every Java class. If a class does not explicitly extend any class, it automatically extends Object. This means all classes inherit a common set of methods from Object.
Method in ObjectSignaturePurpose (ISC Relevant)
toString()public String toString()Returns a String representation. Override to give meaningful output.
equals()public boolean equals(Object obj)Checks logical equality. Default: reference equality (same as ==). Override for value equality.
hashCode()public int hashCode()Returns hash code — linked to equals(). Override together.
getClass()public final Class getClass()Returns the runtime class of the object. Cannot override.
clone()protected Object clone()Creates a copy of the object.
Overriding toString() and equals() Java
class Point {  // implicitly extends Object
    int x, y;

    Point(int x, int y) { this.x = x; this.y = y; }

    @Override
    public String toString() {       // overrides Object.toString()
        return "(" + x + ", " + y + ")";
    }

    @Override
    public boolean equals(Object obj) {   // overrides Object.equals()
        if (this == obj) return true;
        if (!(obj instanceof Point)) return false;
        Point other = (Point) obj;
        return this.x == other.x && this.y == other.y;
    }
}

class Main {
    public static void main(String[] args) {
        Point p1 = new Point(3, 4);
        Point p2 = new Point(3, 4);
        System.out.println(p1);            // calls toString() → (3, 4)
        System.out.println(p1.equals(p2)); // → true (value equality)
        System.out.println(p1 == p2);       // → false (reference equality)
        System.out.println(p1.getClass().getName()); // → "Point"
    }
}
07

Polymorphism & Dynamic Binding

Polymorphism — "many forms" — is the ability of an object to take on many forms. It is the third pillar of OOP (after Encapsulation and Inheritance). Java supports two types.

🕐 Compile-time Polymorphism

Also called static binding or method overloading. The method call is resolved by the compiler at compile time based on method signatures. Less flexible — binding is fixed before runtime.


Resolved at: COMPILE TIME

⚡ Runtime Polymorphism

Also called dynamic binding or method overriding. The method call is resolved at runtime based on the actual type of the object (not the reference type). This is the heart of OOP power.


Resolved at: RUNTIME

Dynamic Binding (Late Binding)
In Java, when an overridden method is called through a superclass reference, Java determines at runtime which version to execute — based on the actual object type, not the declared reference type. This is called dynamic dispatch or late binding.
Subclass Polymorphism + Dynamic Binding Java
abstract class Shape {
    abstract void draw();
    void describe() { System.out.println("I am a shape."); }
}

class Circle    extends Shape {
    @Override void draw() { System.out.println("Drawing CIRCLE"); }
}
class Rectangle extends Shape {
    @Override void draw() { System.out.println("Drawing RECTANGLE"); }
}
class Triangle  extends Shape {
    @Override void draw() { System.out.println("Drawing TRIANGLE"); }
}

class Main {
    public static void main(String[] args) {

        // POLYMORPHIC array — Shape ref, different object types
        Shape[] shapes = {
            new Circle(),
            new Rectangle(),
            new Triangle(),
            new Circle()
        };

        // Same call → different results based on ACTUAL object type
        // This is DYNAMIC BINDING in action!
        for (Shape s : shapes) {
            s.draw();   // resolved at runtime — which draw() to call?
        }

        // OUTPUT:
        // Drawing CIRCLE
        // Drawing RECTANGLE
        // Drawing TRIANGLE
        // Drawing CIRCLE

        // Upcasting (implicit) — always safe
        Shape ref = new Circle();   // Circle IS-A Shape ✅
        ref.draw();                   // calls Circle.draw() at runtime

        // Downcasting (explicit) — needs instanceof check
        if (ref instanceof Circle) {
            Circle c = (Circle) ref;  // safe downcast
        }
    }
}
🎯
The Golden Rule of Dynamic Binding

The reference type determines what methods you can call (compile-time check). The object type (actual runtime type) determines which version of that method runs. This is the essence of runtime polymorphism.

ConceptUpcastingDowncasting
DirectionSubclass → Superclass referenceSuperclass ref → Subclass reference
SafetyAlways safe (implicit)May throw ClassCastException
Cast keywordNot neededExplicit: (SubclassName)
Best practiceUsed widely in polymorphismAlways use instanceof first
ExampleShape s = new Circle();Circle c = (Circle) s;
⭐ Exam Tips — Polymorphism
  • Key rule: Method resolution in dynamic binding: reference type for compile-time check; object type for runtime execution.
  • Variable access (fields) uses the reference type — NOT the object type. This is the difference between method overriding and variable hiding.
  • instanceof tests whether an object is an instance of a given class or its subclass.
  • Polymorphic arrays (Animal[] arr = {new Dog(), new Cat()}) are a classic ISC exam pattern — study them well.
  • Dynamic binding only applies to instance methods — NOT static methods, NOT variables.
08

Interfaces in Java

Interfaces solve a critical design problem: sometimes a class designer wants to enforce a contract (what methods must exist) without dictating how they work. Interfaces are Java's way of achieving this — and also of enabling multiple inheritance.

Definition — Interface
An interface in Java is a completely abstract type that specifies a set of method signatures (contracts) that a class must implement. It defines WHAT to do, not HOW to do it. Declared with keyword interface. A class implements an interface using the keyword implements.
💡
ISC Motivation for Interfaces — CRITICAL CONCEPT

When creating a reusable Sorter class, the class designer knows how to sort, but doesn't know what criterion to use (which field? ascending or descending?). By using an interface (e.g., Comparable), the designer delegates the comparison logic to the end user of the class — who knows the business rules. This is the defining motivation for interfaces.

«interface»
Drawable
+ draw() : void
+ getArea() : double
↓ implements
Implements
Circle
Implements
Rectangle
Implements
Triangle
Interface Declaration + Implementation Java
// INTERFACE — defines a contract
interface Drawable {
    // All methods are implicitly public abstract
    void draw();
    double getArea();

    // All fields are implicitly public static final (constants)
    double PI = 3.14159;  // same as: public static final double PI = 3.14159
}

// Another interface
interface Resizable {
    void resize(double factor);
}

// CLASS implementing ONE interface
class Circle implements Drawable {
    double radius;

    Circle(double r) { this.radius = r; }

    @Override
    public void draw() {
        System.out.println("Drawing circle with radius " + radius);
    }

    @Override
    public double getArea() { return PI * radius * radius; }
}

// CLASS implementing MULTIPLE interfaces (solves diamond problem!)
class Square implements Drawable, Resizable {
    double side;

    Square(double s) { this.side = s; }

    @Override
    public void draw()    { System.out.println("Drawing square, side " + side); }

    @Override
    public double getArea() { return side * side; }

    @Override
    public void resize(double factor) {
        side *= factor;
        System.out.println("Square resized to side: " + side);
    }
}

class Main {
    public static void main(String[] args) {
        Drawable[] shapes = { new Circle(5), new Square(4) };
        for (Drawable d : shapes) {
            d.draw();
            System.out.println("Area: " + d.getArea());
        }

        Square sq = new Square(3);
        sq.resize(2.0);  // from Resizable
        sq.draw();       // from Drawable
    }
}

Practical Interface — Comparable (User-defined sorting)

Comparable Interface — ISC Motivation Example Java
// Interface for comparing — end user defines the logic
interface Comparable {
    int compareTo(Object other);
    // Returns: negative if this < other, 0 if equal, positive if this > other
}

// Student class — USER decides: compare by marks
class Student implements Comparable {
    String name;
    int    marks;

    Student(String n, int m) { name = n; marks = m; }

    @Override
    public int compareTo(Object other) {
        Student s = (Student) other;
        return this.marks - s.marks; // ascending by marks
    }
}

// Reusable Sorter — works for ANY Comparable class!
class Sorter {
    static void bubbleSort(Comparable[] arr) {
        int n = arr.length;
        for (int i = 0; i < n-1; i++) {
            for (int j = 0; j < n-i-1; j++) {
                if (arr[j].compareTo(arr[j+1]) > 0) {
                    Comparable tmp = arr[j];
                    arr[j] = arr[j+1]; arr[j+1] = tmp;
                }
            }
        }
    }
}

class Main {
    public static void main(String[] args) {
        Student[] students = {
            new Student("Priya", 87),
            new Student("Aarav", 92),
            new Student("Rahul", 75)
        };
        Sorter.bubbleSort(students);
        for (Student s : students)
            System.out.println(s.name + ": " + s.marks);
        // Output: Rahul: 75, Priya: 87, Aarav: 92
    }
}

Interface vs Abstract Class vs Concrete Class

FeatureInterfaceAbstract ClassConcrete Class
Keywordinterfaceabstract classclass
Instantiation
MethodsAbstract only (default: public abstract)Both abstract + concreteConcrete only
FieldsConstants only (public static final)Both constants + instance varsInstance variables
Constructor❌ None✅ Yes✅ Yes
Multiple inheritance✅ A class can implement many❌ Only one❌ Only one
Access modifiers (methods)Always publicAny modifierAny modifier
Used forContract / CapabilityPartial implementationFull implementation
📝
Interface Word — Two Different Meanings (ISC Emphasis)

The word "interface" has two meanings: (1) In everyday English, it means the set of method prototypes of a class — what a class exposes publicly. (2) In Java, interface is a specific language construct that defines a pure abstract type with no implementation. The ISC exam explicitly asks you to distinguish these two — always clarify which you mean.

Interface Extending Interface Java
// Interfaces can extend other interfaces using 'extends'
interface Printable {
    void print();
}

interface Saveable extends Printable {  // interface extends interface
    void save(String filename);
}

class Document implements Saveable {    // must implement both print() AND save()
    String content;

    Document(String c) { content = c; }

    @Override
    public void print()                     { System.out.println(content); }

    @Override
    public void save(String filename)       { System.out.println("Saving to: " + filename); }
}
⭐ Exam Tips — Interfaces
  • All methods in an interface are implicitly public and abstract — you don't need to write these modifiers (but you can).
  • All fields in an interface are implicitly public, static, and final — i.e., constants.
  • A class can implement multiple interfaces: class X implements A, B, C { ... }
  • An interface can extend multiple interfaces: interface C extends A, B { }
  • If a class doesn't implement all interface methods, it must be declared abstract.
  • Interfaces cannot have constructors — they are not classes.
  • The key motivation: interfaces allow unrelated classes to share a common behaviour contract without forcing them into the same inheritance hierarchy.

⚡ Quick Reference — Revision Card

extends
Class inherits from another class. Single or multilevel only.
implements
Class implements an interface. Can implement multiple.
super()
Calls parent constructor — MUST be first line in constructor.
super.method()
Calls overridden method of parent class from subclass.
@Override
Annotation to confirm method overriding. Recommended always.
abstract class
Cannot instantiate. Can have abstract + concrete methods.
abstract method
No body. Subclass MUST implement. Class must also be abstract.
protected
Accessible in same package + all subclasses. Best for inheritance fields.
Dynamic binding
Runtime resolution of overridden methods based on OBJECT type (not reference type).
Upcasting
Subclass → Superclass ref. Always safe, implicit. Enables polymorphism.
instanceof
Tests if object is of a given type. Use before downcasting.
Interface fields
Always public + static + final (constants). No instance variables.
Interface methods
Always public + abstract (unless default/static in Java 8+).
Object class
Root of all Java classes. toString(), equals(), hashCode(), getClass().
IS-A test
Use inheritance only when child IS-A parent. Otherwise use composition (HAS-A).
Multiple inheritance
Not via classes in Java. Achievable via interfaces.

🎯 Practice Quiz

10 carefully curated questions — covering all ISC exam patterns for this topic.

Q1 / 10
What does the super() call inside a subclass constructor do?
Q2 / 10
Which access modifier makes a member accessible in the same package AND in subclasses from different packages?
Q3 / 10
Which of the following statements about abstract classes is INCORRECT?
Q4 / 10
What is dynamic binding (runtime polymorphism)?
Q5 / 10
Which of the following is TRUE about interfaces in Java?
Q6 / 10
Consider: Animal a = new Dog(); When a.sound() is called (method overridden in Dog), which version runs?
Q7 / 10
Why does Java NOT support multiple inheritance through classes?
Q8 / 10
What happens if a class implements an interface but does NOT provide the implementation for one of its methods?
Q9 / 10
Which method from the Object class is AUTOMATICALLY called when an object is used in a System.out.println()?
Q10 / 10
You have Shape s = new Circle();. Which operation requires an explicit cast?