Favoring Composition Over Inheritance In Java With Examples
Last Updated :
17 Mar, 2025
In object-oriented programming (OOP), choosing between inheritance and composition is crucial for designing flexible and maintainable code. This article explores why you should favor composition over inheritance, with simple explanations and examples.
What is Inheritance?
Inheritance is when a new class is based on an existing class. The new class (subclass) inherits properties and methods from the existing class (superclass). This relationship is known as "is-a." For example, an Employee
"is a" Person
because it inherits from the Person
class.
Example:
Java
class Person {
// Private fields for encapsulation
private String name;
private int age;
// Constructor to initialize fields
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
this.age = age;
}
}
class Employee extends Person {
// Private field for encapsulation
private int salary;
// Constructor to initialize fields
public Employee(String name, int age, int salary) {
super(name, age); // Call superclass constructor
this.salary = salary;
}
// Getter for salary
public int getSalary() {
return salary;
}
// Setter for salary
public void setSalary(int salary) {
this.salary = salary;
}
// Method to display employee information
public void displayInfo() {
System.out.println("Name: " + getName());
System.out.println("Age: " + getAge());
System.out.println("Salary: " + salary);
}
}
public class Main {
public static void main(String[] args) {
// Create an Employee object
Employee emp = new Employee("Geek1", 30, 50000);
// Display employee information
emp.displayInfo();
}
}
OutputName: Geek1
Age: 30
Salary: 50000
In this example, the Employee
class inherits from Person
and adds a new property, salary
.
What is Composition?
Composition involves creating classes that include instances of other classes. This is known as a "has-a" relationship. For example, a Person
"has an" Address
because it contains an Address
object.
Example:
Java
class Address {
// Private fields for encapsulation
private String street;
private String city;
private String zipCode;
// Constructor to initialize fields
public Address(String street, String city, String zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
// Getter for street
public String getStreet() {
return street;
}
// Setter for street
public void setStreet(String street) {
this.street = street;
}
// Getter for city
public String getCity() {
return city;
}
// Setter for city
public void setCity(String city) {
this.city = city;
}
// Getter for zipCode
public String getZipCode() {
return zipCode;
}
// Setter for zipCode
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
// Method to display address (delegation)
public void displayAddress() {
System.out.println(street + ", " + city + ", " + zipCode);
}
}
class Person {
// Private fields for encapsulation
private String name;
private Address address;
// Constructor to initialize fields
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for address
public Address getAddress() {
return address;
}
// Setter for address
public void setAddress(Address address) {
this.address = address;
}
// Method to display person information
public void displayInfo() {
System.out.println("Name: " + name);
System.out.print("Address: ");
address.displayAddress();
}
}
public class Main {
public static void main(String[] args) {
// Create an Address object
Address addr = new Address("123 Main St", "Springfield", "12345");
// Create a Person object
Person person = new Person("Geek1", addr);
// Display person information
person.displayInfo();
}
}
OutputName: Geek1
Address: 123 Main St, Springfield, 12345
In this example, the Person
class uses composition to include an Address
object. This creates a "has-a" relationship between Person
and Address
.
Why Favor Composition Over Inheritance?
- Flexibility: With composition, you can easily change or replace components (like
Address
) without affecting the Person
class. - Encapsulation: Composition keeps the details of the composed class (like
Address
) hidden from the outside, making your code more secure and easier to manage. - Avoid Fragile Base Class Problem: Changes in a superclass can break subclasses. Composition reduces this risk because changes in one class do not directly impact others.
- Better Testability: Composition makes it easier to test individual components by substituting mock objects if needed.
Conclusion
Favoring composition over inheritance is a best practice in OOP that leads to more flexible, maintainable, and testable code. By using composition, you create "has-a" relationships that are often more adaptable and less prone to problems than "is-a" relationships from inheritance.
Similar Reads
Using final with Inheritance in Java Prerequisite - Overriding in java, Inheritance final is a keyword in java used for restricting some functionalities. We can declare variables, methods, and classes with the final keyword. Using final with inheritance During inheritance, we must declare methods with the final keyword for which we are
4 min read
Difference between Inheritance and Composition in Java When we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class. In doing this, we can reuse the fields and methods of the existing class without having to write them ourself.A subclass inherits all the
3 min read
Comparison of Inheritance in C++ and Java The purpose of inheritance is the same in C++ and Java. Inheritance is used in both languages for reusing code and/or creating an âis-aâ relationship. The following examples will demonstrate the differences between Java and C++ that provide support for inheritance. 1) In Java, all classes inherit fr
4 min read
Delegation vs Inheritance in Java Inheritance in Java programming is the process by which one class takes the property of another other class. i.e. the new classes, known as derived or child class, take over the attributes and behavior of the pre-existing classes, which are referred to as base classes or super or parent class.Delega
3 min read
Open Closed Principle in Java with Examples In software development, the use of object-oriented design is crucial. It helps to write flexible, scalable, and reusable code. It is recommended that the developers follow SOLID principles when writing a code. One of the five SOLID principles is the open/closed principle. The principle states that
9 min read
Java - Covariant Method Overriding with Examples The covariant method overriding approach, implemented in Java 5, helps to remove the client-side typecasting by enabling you to return a subtype of the overridden method's actual return type. Covariant Method overriding means that when overriding a method in the child class, the return type may vary
4 min read