Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Mastering Inheritance and Polymorphism in Java

Tech Jun 11 1
  1. Understanding Inheritance

Inheritance is a fundamental mechanism in Object-Oriented Programming (OOP) that allows a new class to adopt the attributes and behaviors of an existing class. This promotes code reusability and establishes a hierarchical relationship between classes. The existing class is often referred to as the Superclass (or Parent class), while the new class is the Subclass (or Child class). This relationship is typically described as an is-a relationship.

1.1 Syntax and Basic Example

In Java, the extends keyword is used to establish inheritance.

// Base class
class LivingBeing {
    String speciesName;
    int lifespan;

    public void breathe() {
        System.out.println(speciesName + " is breathing.");
    }
}

// Derived class
class Mammal extends LivingBeing {
    public void walk() {
        System.out.println(speciesName + " is walking.");
    }
}

public class InheritanceTest {
    public static void main(String[] args) {
        Mammal human = new Mammal();
        human.speciesName = "Homo Sapiens";
        human.lifespan = 80;
        
        // Accessing inherited method
        human.breathe();
        // Accessing own method
        human.walk();
    }
}

1.2 Accessing Parent Members (super keyword)

The super keyword is essential for referencing the immediate parent class. It is commonly used to access parent attributes or methods that are hidden by child class declarations.

class Parent {
    String data = "Parent Data";
    
    public void display() {
        System.out.println("Parent Display");
    }
}

class Child extends Parent {
    String data = "Child Data";

    public void showInfo() {
        System.out.println("Child data: " + this.data);
        // Accessing parent's version of 'data'
        System.out.println("Parent data: " + super.data);
        // Calling parent's method explicitly
        super.display();
    }
}

1.3 Method Overriding

Method overriding occurs when a subclass provides a specific implementation for a method already defined in its superclass. The method signature (name and parameters) must be identical.

class Device {
    public void powerOn() {
        System.out.println("Generic device powering on.");
    }
}

class Smartphone extends Device {
    @Override
    public void powerOn() {
        System.out.println("Smartphone booting up with logo.");
    }
}

1.4 Constructor Chaining

In Java, the constructor of the parent class is always executed before the constructor of the child class. If you do not explicitly call a parent constructor using super(), the compiler inserts a call to the no-argument constructor of the parent class automatically.

class Base {
    Base(String id) {
        System.out.println("Base initialized with ID: " + id);
    }
}

class Derived extends Base {
    Derived() {
        // Must explicitly call super because Base has no default constructor
        super("XYZ-123");
        System.out.println("Derived initialized.");
    }
}

1.5 Inheritance Rules

  • Single Inheritance: A class can only extend one direct superclass.
  • Multilevel Inheritance: A class can be a parent of another class, which in turn is a parent of a third class (e.g., A -> B -> C).
  • Private Members: Subclasses inherit private fields, but they cannot access them directly. They must use public getter/setter methods.
  1. Access Modifiers

Java defines access levels that control where members can be accessed.

Modifier Class Package Subclass (Diff Package) World
public Yes Yes Yes Yes
protected Yes Yes Yes No
default Yes Yes No No
private Yes No No No
  1. The Object Class

All classes in Java implicitly extend java.lang.Object. This root class provides standard methods that every object inherits.

3.1 Common Object Methods

  • toString(): Returns a string representation of the object. It is good practice to override this for debugging.
  • equals(Object obj): Compares the equality of objects. By default, it checks reference equality (==), but it is often overridden to check logical equality (e.g., comparing field values).
  • hashCode(): Returns a hash code value for the object. If two objects are equal according to equals(), they must have the same hash code.
  • getClass(): Returns the runtime class of the object, useful for reflection.
class User {
    private String userId;
    private int level;

    public User(String userId, int level) {
        this.userId = userId;
        this.level = level;
    }

    @Override
    public String toString() {
        return "User{id='" + userId + "', level=" + level + "}";
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return level == user.level && userId.equals(user.userId);
    }
}

  1. Polymorphism

Polymorphism allows objects of different subclasses to be treated as objects of a common superclass. It enables one interface to be used for a general class of actions.

4.1 Principles of Polymorphism

To achieve polymorphism, you need:

  1. Inheritance: A relationship between a parent and child class.
  2. Method Overriding: The child class must redefine a method from the parent.
  3. Upcasting: A parent class reference variable pointing to a child class object.

4.2 Upcasting and Dynamic Method Dispatch

When a parent reference points to a child object, the call to an overridden method is determined at runtime (Dynamic Method Dispatch). The decision of which method to execute is based on the actual object in the heap, not the reference type.

class Shape {
    public void draw() {
        System.out.println("Drawing a generic shape.");
    }
}

class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle.");
    }
}

class Square extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a Square.");
    }
}

public class PolyDemo {
    public static void render(Shape s) {
        // Polymorphic behavior: The specific draw() method is called
        // based on whether 's' is a Circle or Square at runtime.
        s.draw();
    }

    public static void main(String[] args) {
        Shape sh1 = new Circle(); // Upcasting
        Shape sh2 = new Square(); // Upcasting
        
        render(sh1); // Output: Drawing a Circle.
        render(sh2); // Output: Drawing a Square.
    }
}

4.3 Downcasting and instanceof

While upcasting is automatic, downcasting (converting a parent reference back to a child type) must be explicit. To avoid ClassCastException, use the instanceof operator to check the actual type before casting.

public class CastingDemo {
    public static void main(String[] args) {
        Shape myShape = new Circle();

        if (myShape instanceof Circle) {
            Circle specificCircle = (Circle) myShape;
            System.out.println("Successfully downcasted to Circle.");
        } else if (myShape instanceof Square) {
            Square specificSquare = (Square) myShape;
        }
    }
}

4.4 Member Access in Polymorphism

  • Methods: "Compile-time check, Runtime execution." The compiler checks the reference type, but the JVM executes the method of the actual object type.
  • Variables: Variables are not polymorphic. Access is determined by the reference type (the left side of the assignment), not the object type.
Tags: Java

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.