Skip to main content

Inheritance

Definition​

  • Inheritance is the process of writing a new class by inheriting commonly used state and behavior of an existing class.

Terminology​

  • Existing class β†’ Super Class / Base Class / Parent Class
  • New class β†’ Sub Class / Derived Class / Child Class

Key Points​

  • Inheritance is an important feature of OOPs
  • Main goal: Code Reusability
    • Reuse properties and operations of an existing class in a new class

Types of Inheritance

  1. Simple Inheritance
  2. Multilevel Inheritance
  3. Hierarchical Inheritance
  4. Multiple Inheritance (Not directly supported in Java using classes)
  5. Hybrid Inheritance

1. Simple Inheritance

Concept​

  • One super class and one sub class

Diagram​

A (Super class)
↑
B (Sub class)

Example​

class A {
// properties and methods
}

class B extends A {
// inherits from A
}

2. Multilevel Inheritance

Concept​

  • Chain of inheritance (one after another)

Rules​

  • One super class can have:
    • One direct sub class
    • Many indirect sub classes
  • One sub class can have:
    • One direct super class
    • Many indirect super classes

Diagram​

A
↑
B
↑
C

Example​

class A {
// base class
}

class B extends A {
// inherits A
}

class C extends B {
// inherits B (and indirectly A)
}

Important Notes

  • Java does NOT support multiple inheritance with classes
  • But it can be achieved using:
    • Interfaces

Hierarchical Inheritance

Concept​

  • One super class can have many direct sub classes
  • One sub class can have only one direct super class

Diagram​

A
/ \
B C

Example​

class A {
// base class
}

class B extends A {
// inherits A
}

class C extends A {
// inherits A
}

Multiple Inheritance

Concept​

  • One sub class can have many direct super classes
  • One super class can have only one direct sub class

Diagram​

A B
\ /
C

Example (Invalid in Java)​

class A { }

class B { }

class C extends A, B { }// INVALID

Important Rule​

  • Java does NOT support multiple inheritance using classes
  • Java supports multiple inheritance using interfaces

Hybrid Inheritance

Concept​

  • Combination of two or more inheritance types

Invalid Combination​

(Multiple + Hierarchical + Multilevel)

A B
\ /
C
/ \
D E

➑️ Not allowed because it involves multiple inheritance with classes


Valid Combination​

(Hierarchical + Multilevel)

A
/ \
B C
/ \
D E

Key Points

  • Hierarchical β†’ One parent, many children
  • Multilevel β†’ Chain (A β†’ B β†’ C)
  • Multiple β†’ Not allowed with classes
  • Hybrid β†’ Allowed only if it does NOT involve multiple inheritance via classes

Lab417.java​

class Lab417 {

public static void main(String[] args) {
Hai hai = new Hai();
System.out.println(hai.a);
System.out.println(hai.b); // Error (b not in Hai)

Hello hello = new Hello();
System.out.println(hello.a); // Error (a not in Hello)
System.out.println(hello.b);
}
}

class Hai {

int a = 99;
}

class Hello {

int b = 88;
}

Lab418.java​

class Lab418 {

public static void main(String[] args) {
Hai hai = new Hai();
System.out.println(hai.a); // βœ” accessible
System.out.println(hai.b); // not accessible

Hello hello = new Hello();
System.out.println(hello.a); // βœ” inherited
System.out.println(hello.b); // βœ” accessible
}
}

class Hai {

int a = 99;
}

class Hello extends Hai {

int b = 88;
}

Lab419.java​

class Lab419 {

public static void main(String[] args) {
Hai hai = new Hai();
System.out.println(hai.a); // βœ” possible

Hello hello = new Hello();
System.out.println(hello.a); // βœ” inherited
System.out.println(hello.b); // βœ” own property
}
}

class Hai {

int a = 99;
}

class Hello extends Hai {

int b = 88;
}

Lab420.java​

class Lab420 {

public static void main(String[] args) {
Hello hello = new Hello();
hello.m1(); // βœ” possible (inherited method)
hello.m2(); // βœ” possible
}
}

class Hai {

int a = 99;

void m1() {
System.out.println("Hai -> m1 :" + a);
System.out.println("Hai -> m1 :" + b); // Error (b not in Hai)
}
}

class Hello extends Hai {

int b = 88;

void m2() {
System.out.println("Hello -> m2 :" + a); // βœ” inherited
System.out.println("Hello -> m2 :" + b);
}
}

Key Concepts from this Page

Without Inheritance​

  • Classes cannot access each other’s variables

With Inheritance (extends)​

  • Subclass can access:
    • Parent class variables
    • Parent class methods

Parent Class Limitation​

  • Parent cannot access child members

Method Access​

  • Child object can call:
    • Parent methods
    • Its own methods

🧠 Simple Rule to Remember

πŸ‘‰ Flow is always downward (Parent β†’ Child)

πŸ‘‰ Not upward (Child β†’ Parent)

Lab421.java​

class Lab421 {

public static void main(String[] args) {
Hello hello = new Hello();
hello.m1();
hello.m2();
}
}

class Hai {

int a = 99;

void m1() {
System.out.println("Hai -> m1 :" + a);
}
}

class Hello extends Hai {

int b = 88;

void m2() {
System.out.println("Hello -> m2 :" + a);
System.out.println("Hello -> m2 :" + b);
}
}

Lab422.java​

class Lab422 {

public static void main(String[] args) {
C cobj = new C();
cobj.m1();
cobj.m2();
cobj.m3();
}
}

class A {

void m1() {
System.out.println("A -> m1");
}
}

class B extends A {

void m2() {
System.out.println("B -> m2");
}
}

class C extends B {

void m3() {
System.out.println("C -> m3");
}
}

Lab423.java​

class Lab423 {

public static void main(String[] args) {
B bobj = new B();
bobj.m1();
bobj.m2();

C cobj = new C();
cobj.m1();
cobj.m3();
}
}

class A {

void m1() {
System.out.println("A -> m1");
}
}

class B extends A {

void m2() {
System.out.println("B -> m2");
}
}

class C extends A {

void m3() {
System.out.println("C -> m3");
}
}

Lab424.java​

class Lab424 {
public static void main(String[] args) {
System.out.println("Hello Guys");
}
}

class A { }

class B { }

// Invalid - Multiple inheritance using class es
class C extends A, B { }


Lab425.java​

class Lab425 {
public static void main(String[] args) {
System.out.println("Hello Guys");
}
}

class Hai { }

// Invalid - Multiple inheritance
class Hello extends Object, Hai { }


Key Concepts from this Page

Single Inheritance​

  • One class extends another
  • Child can access parent methods

Multilevel Inheritance​

  • Chain: A β†’ B β†’ C
  • Child can access all parent methods

Hierarchical Inheritance​

  • One parent β†’ multiple children
  • Each child accesses parent separately

Multiple Inheritance (Classes)​

  • Not supported in Java
  • Causes compile-time error

🧠 Quick Summary

  • extends β†’ used for inheritance
  • Java supports:
    • Single
    • Multilevel
    • Hierarchical
  • Java does NOT support:
    • Multiple inheritance using classes

Lab426.java​

class Lab426 {

public static void main(String[] args) {
System.out.println("Hello Guys");
}
}

// Invalid: cyclic inheritance (class extending itself)
class A extends A {}

Lab427.java​

class Lab427 {

public static void main(String[] args) {
System.out.println("Hello Guys");
}
}

// Invalid: cyclic inheritance
class A extends B {}

class B extends A {}

Lab428.java​

class Lab428 {

public static void main(String[] args) {
System.out.println("Hello Guys");
}
}

// Invalid: final class cannot be extended
final class A {}

class B extends A {} // Compile-time error

3.5.1 Inheritance and Blocks


Lab429.java​

class Lab429 {

public static void main(String[] args) {
new Hello();
}
}

class Hai {

static int a = 99;

static {
System.out.println("Hai -> S.B. :" + a);
}
}

class Hello extends Hai {

static int b = 88;

static {
System.out.println("Hello -> S.B. :" + a);
System.out.println("Hello -> S.B. :" + b);
}
}

Lab430.java​

class Lab430 {

public static void main(String[] args) {
System.out.println(Hello.a);
}
}

class Hai {

static {
System.out.println("Hai -> S.B.");
}
}

class Hello extends Hai {

static int a = 99;

static {
System.out.println("Hello -> S.B.");
}
}

Lab431.java​

class Lab431 {

public static void main(String[] args) {
System.out.println(Hai.a);
}
}

class Hai {

static int a = 99;

static {
System.out.println("Hai -> S.B.");
}
}

class Hello extends Hai {

static {
System.out.println("Hello -> S.B.");
}
}

Key Concepts from this Page

Cyclic Inheritance​

  • class A extends A β†’ Not allowed
  • A extends B and B extends A β†’ Not allowed

Final Class​

  • final class A {} β†’ cannot be extended
  • Prevents inheritance

Static Blocks + Inheritance​

Important Rules:​

  1. Static blocks execute when class is loaded
  2. Parent class loads before child class
  3. Static variables are initialized before static block execution
  4. Accessing a static member triggers class loading

🧠 Execution Order Insight

Lab429:​

Hai static block runs first
Hello static block runs next

Lab430:​

Access Hello.a β†’
1. Load Hai β†’ run Hai static block
2. Load Hello β†’ run Hello static block
3. Print value

Lab431:​

Access Hai.a β†’
Only Hai class loads
Hello is NOT loaded

⚑ Quick Summary

  • No cyclic inheritance
  • Cannot extend final class
  • Parent static blocks execute before child
  • Class loads only when needed

Lab432.java​

class Lab432 {

public static void main(String[] args) {
System.out.println(Hello.a);
}
}

class Hai {

static int a = 99;

static {
System.out.println("Hai -> S.B.");
}
}

class Hello extends Hai {

static {
System.out.println("Hello -> S.B.");
}
}

Lab433.java​

class Lab433 {

public static void main(String[] args) {
new Hello();
}
}

class Hai {

int a = 99;

{
System.out.println("Hai -> I.B. :" + a);
}
}

class Hello extends Hai {

int b = 88;

{
System.out.println("Hello -> I.B. :" + a);
System.out.println("Hello -> I.B. :" + b);
}
}

Lab434.java​

class Lab434 {

public static void main(String[] args) {
Hello h = new Hello();
}
}

class Hai {

{
System.out.println("Hai -> I.B.");
}

static {
System.out.println("Hai -> S.B.");
}
}

class Hello extends Hai {

{
System.out.println("Hello -> I.B.");
}

static {
System.out.println("Hello -> S.B.");
}
}

Lab435.java​

class Lab435 {

public static void main(String[] args) {
System.out.println("Hai -> Main");
}

static {
System.out.println("Hai S.B.");
}
}

class Lab435Child extends Hai {

static {
System.out.println("Lab435 S.B.");
}
}

Lab436.java​

class Lab436 {

public static void main(String[] args) {
Hello.show();
}
}

class Hai {

static void show() {
System.out.println("Hai -> show");
}

static {
System.out.println("Hai -> S.B.");
}
}

class Hello extends Hai {

static {
System.out.println("Hello -> S.B.");
}
}

Key Concepts from this Page

1. Static Block Execution​

  • Executes once when class loads
  • Parent class static block executes before child

Example (Lab432 / Lab436):​

Hai -> S.B.
Hello -> S.B.

2. Instance Block Execution​

  • Executes every time object is created
  • Parent instance block runs before child

Example (Lab433):​

Hai -> I.B. :99
Hello -> I.B. :99
Hello -> I.B. :88

3. Static vs Instance Order​

Lab434 Execution Order:​

Hai -> S.B.
Hello -> S.B.
Hai -> I.B.
Hello -> I.B.

4. Important Rules​

Static Members​

  • Loaded at class loading time
  • Access using class name triggers loading

Instance Members​

  • Loaded during object creation
  • Executed every time new is used

5. Static Method Inheritance​

Lab436 Insight:​

  • Static methods are inherited
  • Calling Hello.show() β†’ actually calls method from Hai

Execution:

Hai -> S.B.
Hello -> S.B.
Hai -> show

⚑ Final Summary

  • Static Block β†’ runs once during class loading
  • Instance Block β†’ runs every time object is created
  • Parent executes before child
  • Static methods are inherited (but not overridden like instance methods)

3.5.2 Inheritance and Constructors


Lab437.java​

class Lab437 {

public static void main(String[] args) {
new B();
}
}

class A {

A() {
System.out.println("A -> D.C.");
}
}

class B extends A {

B() {
System.out.println("B -> D.C.");
}
}

Output:​

A -> D.C.
B -> D.C.

Lab438.java​

class Lab438 {

public static void main(String[] args) {
new C();
}
}

class A {

A() {
System.out.println("A -> D.C.");
}
}

class B extends A {

B() {
System.out.println("B -> D.C.");
}
}

class C extends B {

C() {
System.out.println("C -> D.C.");
}
}

Output:​

A -> D.C.
B -> D.C.
C -> D.C.

Lab439.java​

class Lab439 {

public static void main(String[] args) {
new C();
}
}

class A {

A() {
System.out.println("A -> D.C."); // (5)
}

static {
System.out.println("A -> S.B."); // (1)
}

{
System.out.println("A -> I.B."); // (4)
}
}

class B extends A {

B() {
System.out.println("B -> D.C."); // (7)
}

static {
System.out.println("B -> S.B."); // (2)
}

{
System.out.println("B -> I.B."); // (6)
}
}

class C extends B {

C() {
System.out.println("C -> D.C."); // (9)
}

static {
System.out.println("C -> S.B."); // (3)
}

{
System.out.println("C -> I.B."); // (8)
}
}

Execution Order (VERY IMPORTANT)

Final Output Sequence:​

A -> S.B. (1)
B -> S.B. (2)
C -> S.B. (3)

A -> I.B. (4)
A -> D.C. (5)

B -> I.B. (6)
B -> D.C. (7)

C -> I.B. (8)
C -> D.C. (9)

🧠 Key Rules to Remember

1. Static Blocks (S.B.)​

  • Executed once
  • Executed during class loading
  • Order: Parent β†’ Child

2. Instance Blocks (I.B.)​

  • Executed every time object is created
  • Runs before constructor
  • Order: Parent β†’ Child

3. Constructors (D.C.)​

  • Executed after instance blocks
  • Always called Parent β†’ Child

⚑ Full Execution Flow

When new C() is executed:

Step 1: Class Loading​

A β†’ S.B.
B β†’ S.B.
C β†’ S.B.

Step 2: Object Creation​

A β†’ I.B.
A β†’ D.C.

B β†’ I.B.
B β†’ D.C.

C β†’ I.B.
C β†’ D.C.

🎯 Golden Rule

πŸ‘‰ "Static β†’ Instance β†’ Constructor"

πŸ‘‰ "Parent β†’ Child β†’ Parent β†’ Child" (layer-wise execution)