DEV Community

Cover image for Beyond Inheritance in Java: A Practical Guide to Composition
Vinayagam
Vinayagam

Posted on

Beyond Inheritance in Java: A Practical Guide to Composition

Introduction

In Java, inheritance is commonly used to reuse code using the extends keyword. However, inheritance is not always the best solution. In many real-world applications, developers prefer a more flexible and maintainable approach called composition.

This article explains how to share data both with inheritance and without inheritance, using simple examples, a relatable story, and the role of access modifiers.


A Simple Story to Understand

Consider a School and Student relationship:

  • A School does not become a Student
  • A School has Students

This highlights the difference:

  • Inheritance represents an IS-A relationship
  • Composition represents a HAS-A relationship

Using Inheritance (IS-A Relationship)

Student.java

package shop;

public class Student {
    protected String name = "Vinay";

    public void showName() {
        System.out.println(name);
    }
}
Enter fullscreen mode Exit fullscreen mode

School.java

package shop;

public class School extends Student {

    public static void main(String[] args) {
        School sc = new School();
        sc.showName();  // inherited method
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • School extends Student, meaning School is treated as a Student
  • This is not logically correct for this scenario
  • protected allows access within subclasses

Using Composition (Without Inheritance)

Student.java

package shop;

public class Student {
    private String name = "Vinay";

    public String getName() {
        return name;
    }
}
Enter fullscreen mode Exit fullscreen mode

School.java

package shop;

public class School {

    public void display(Student s) {
        System.out.println(s.getName());
    }
}
Enter fullscreen mode Exit fullscreen mode

Main.java

package shop;

public class Main {

    public static void main(String[] args) {
        Student s = new Student();
        School sc = new School();

        sc.display(s);  // HAS-A relationship
    }
}
Enter fullscreen mode Exit fullscreen mode

Role of Access Modifiers

Access modifiers control how data is accessed:

  • private → accessible only within the same class
  • protected → accessible in subclasses
  • public → accessible everywhere

In composition:

  • Data is kept private
  • Access is provided through public getter methods

This improves data security and encapsulation.


Inheritance vs Composition

Feature Inheritance Composition
Relationship IS-A HAS-A
Flexibility Low High
Coupling Tight Loose
Real-world modeling Sometimes incorrect More accurate

When to Use Each

Use inheritance when:

  • There is a clear IS-A relationship
  • Example: Dog is an Animal

Use composition when:

  • There is a HAS-A relationship
  • Example: School has Students

References

Top comments (0)