Chapter 10: Inheritance
Introduction to Inheritance
Inheritance is used to borrow properties & methods from an existing class.
It allows us to create new classes based on existing classes, promoting code reusability and establishing relationships between classes.
Basic Concept
📱 Phone
Super Class
🤖 Smart Phone
Sub Class
Subclass extends Superclass
Vehicle Hierarchy
Animal Hierarchy
Important: Java doesn't support multiple inheritance (i.e., two classes cannot be super classes for a subclass).
Declaring Inheritance in Java
Inheritance in Java is declared using the extends keyword.
// Base class (Superclass)
class Animal {
String name;
int age;
void eat() {
System.out.println(name + " is eating");
}
void sleep() {
System.out.println(name + " is sleeping");
}
}
// Derived class (Subclass)
class Dog extends Animal {
String breed;
void bark() {
System.out.println(name + " is barking");
}
void wagTail() {
System.out.println(name + " is wagging tail");
}
}
public class InheritanceExample {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.name = "Buddy";
myDog.age = 3;
myDog.breed = "Golden Retriever";
// Using inherited methods
myDog.eat(); // From Animal class
myDog.sleep(); // From Animal class
// Using Dog's own methods
myDog.bark();
myDog.wagTail();
}
}
When a class inherits from a superclass, it inherits:
Constructors in Inheritance
When a derived class is extended from the base class, the constructor of the base class is executed first followed by the constructor of the derived class.
Parent Constructor
Base class constructor executes first
Child Constructor
Derived class constructor executes second
Grand Child Constructor
Further derived class constructor executes last
class Parent {
Parent() {
System.out.println("Parent constructor called");
}
Parent(String name) {
System.out.println("Parent constructor with name: " + name);
}
}
class Child extends Parent {
Child() {
System.out.println("Child constructor called");
}
Child(String name) {
super(name); // Call parent constructor with parameter
System.out.println("Child constructor with name: " + name);
}
}
public class ConstructorInheritance {
public static void main(String[] args) {
System.out.println("Creating Child object:");
Child child = new Child();
System.out.println("\nCreating Child object with name:");
Child namedChild = new Child("John");
}
}
Constructor Overloading: When there are multiple constructors in the parent class, the constructor without any parameters is called from the child class by default.
Super Keyword
A reference variable used to refer to the immediate parent class object.
Instance Variables
Can be used to refer immediate parent class instance variable
super.variableName
Methods
Can be used to invoke parent class methods
super.methodName()
Constructors
Can be used to invoke parent class constructors
super(parameters)
class Vehicle {
String brand = "Generic";
int maxSpeed = 100;
void start() {
System.out.println("Vehicle is starting");
}
void displayInfo() {
System.out.println("Brand: " + brand + ", Max Speed: " + maxSpeed);
}
}
class Car extends Vehicle {
String brand = "Toyota"; // Hiding parent variable
int doors = 4;
void start() {
super.start(); // Call parent method
System.out.println("Car engine started");
}
void displayInfo() {
System.out.println("Car Brand: " + brand);
System.out.println("Vehicle Brand: " + super.brand); // Access parent variable
super.displayInfo(); // Call parent method
System.out.println("Doors: " + doors);
}
}
public class SuperKeywordExample {
public static void main(String[] args) {
Car car = new Car();
car.start();
System.out.println();
car.displayInfo();
}
}
Method Overriding
If the child class implements the same method present in the parent class again, it is known as method overriding.
This is also called "Redefining method of super class in sub class".
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
void move() {
System.out.println("Animal moves");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks: Woof! Woof!");
}
@Override
void move() {
System.out.println("Dog runs on four legs");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows: Meow! Meow!");
}
@Override
void move() {
System.out.println("Cat walks silently");
}
}
public class MethodOverriding {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
Cat cat = new Cat();
animal.makeSound(); // Animal makes a sound
dog.makeSound(); // Dog barks: Woof! Woof!
cat.makeSound(); // Cat meows: Meow! Meow!
animal.move(); // Animal moves
dog.move(); // Dog runs on four legs
cat.move(); // Cat walks silently
}
}
Rules for Method Overriding:
Dynamic Method Dispatch
Dynamic method dispatch is used to achieve runtime polymorphism in Java.
It allows Java to decide which method to call at runtime based on the actual object type.
Scenario 1: Allowed
Super obj = new Sub();
obj.method1(); // Sub's method called
obj.method3(); // Not Allowed - method doesn't exist in Super
Result: Method of actual object (Sub) is called
Scenario 2: Not Allowed
Sub obj = new Super();
Result: Compilation error - cannot assign parent to child reference
class Shape {
void draw() {
System.out.println("Drawing a shape");
}
void area() {
System.out.println("Calculating area of shape");
}
}
class Circle extends Shape {
@Override
void draw() {
System.out.println("Drawing a circle");
}
@Override
void area() {
System.out.println("Area = π × r²");
}
void circumference() {
System.out.println("Circumference = 2 × π × r");
}
}
class Rectangle extends Shape {
@Override
void draw() {
System.out.println("Drawing a rectangle");
}
@Override
void area() {
System.out.println("Area = length × width");
}
}
public class DynamicDispatch {
public static void main(String[] args) {
// Dynamic method dispatch
Shape shape1 = new Circle(); // Allowed
Shape shape2 = new Rectangle(); // Allowed
shape1.draw(); // Calls Circle's draw method
shape1.area(); // Calls Circle's area method
shape2.draw(); // Calls Rectangle's draw method
shape2.area(); // Calls Rectangle's area method
// shape1.circumference(); // Not allowed - method not in Shape class
// To call circumference, we need to cast
if (shape1 instanceof Circle) {
((Circle) shape1).circumference();
}
}
}
Practice Set
Chapter 10 - Practice Set
1. Circle and Cylinder
Create a class Circle and use inheritance to create another class Cylinder from it.
2. Rectangle and Cuboid
Create a class Rectangle and use inheritance to create another class Cuboid. Try to keep it as close to real world scenario as possible.
3. Area and Volume Methods
Create methods for area and volume in problem 1.
4. Getters and Setters
Create methods for area & volume in problem 2. Also create getters and setters.
5. Constructor Execution Order
What is the order of constructor execution for the following inheritance hierarchy?
Base → Derived1 → Derived2
Derived2 obj = new Derived2();
Which constructor(s) will be executed & in what order?