CodeGym /Java Blog /OOP Java /Relationships between classes. Inheritance, composition, ...
Author
Vasyl Malik
Senior Java Developer at CodeGym

Relationships between classes. Inheritance, composition, and aggregation

Published in the OOP Java group
Hi! Today we'll take a closer look at one principle of Object Oriented Programming (OOP): Inheritance. We'll also study other types of relationships between classes: composition and aggregation. Relationships between classes. Inheritance, composition, and aggregation - 1This topic won't be difficult: you've already encountered inheritance and examples of inheritance many times in past lessons. Today, the main thing will be to reinforce your knowledge, examine the mechanism of inheritance in greater detail, and once again run through some examples. :) Well, let's go!

Inheritance in Java and its advantages

As you surely remember, inheritance is a mechanism that lets you describe a new class based on an existing class (parent class). In doing so, the new class borrows the properties and functionality of the parent class. Let's recall an example of inheritance given in previous lessons:

public class Car {

   private String model;
   private int maxSpeed;
   private int yearOfManufacture;

   public Car(String model, int maxSpeed, int yearOfManufacture) {
       this.model = model;
       this.maxSpeed = maxSpeed;
       this.yearOfManufacture = yearOfManufacture;
   }


public void gas() {
       // Gas
   }

   	public void brake() {
       // Brake
   }
}


public class Truck extends Car {

   public Truck(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}



public class Sedan extends Car {
   public Sedan(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}
We have a certain program that involves working with various types of cars. Even if you're not a car enthusiast, you probably know that there are a great many types of cars in the world. :) Accordingly, we'll separate the common properties of cars into a common parent class called Car. So what's common to all cars, regardless of their type? Every car has a year of manufacture, model name, and maximum speed. We put these properties into the model, maxSpeed, and yearOfManufacture fields. As for behavior, any car can accelerate and slow down. :) We define this behavior in the gas() and brake() methods. What benefits does this give us? First of all, it reduces the amount of code. Of course, we can do without the parent class. But since each car must be able to accelerate and slow down, we'll have to create gas() and brake() methods in the Truck, Sedan, F1Car, and SportsCar classes and in every other car class. Imagine how much extra code we would have to write. And don't forget about the model, maxSpeed, and yearOfManufacture fields: if we get rid of the parent class, we'll have to create them in each car class! Relationships between classes. Inheritance, composition, and aggregation - 2When we have a couple dozen car classes, the amount of duplicate code becomes really serious. Moving common fields and methods (also called "states" and "behaviors") to a parent class lets us save a lot of time and space. If some type has unique properties or methods that other car types don't have, no big deal. You can always create them in a descendant class, separate from everyone else.

public class F1Car extends Car {

   public void pitStop() {

       // Only race cars make pit stops
   }

   public static void main(String[] args) {

       F1Car formula1Car = new F1Car();
       formula1Car.gas();
       formula1Car.pitStop();
       formula1Car.brake();
   }
}
Let's look at Formula One race cars as an example. Unlike their "relatives", they have a unique behavior — they take a pit stop from time to time. This doesn't bother us. We've already described the common behavior in the Car parent class, and the specific behavior of descendant classes can be added to those classes. Relationships between classes. Inheritance, composition, and aggregation - 3The same is true of fields: if a child class has unique properties, we calmly declare these fields inside the child class and stop worrying. :) The ability to reuse code is the main advantage of inheritance. For programmers, it's very important to not write extra code. You'll come across this repeatedly in your work. Please remember something else crucial: Java doesn't have multiple inheritance. Each class inherits only one class. We'll talk more about the reasons for this in future lessons. For now, just remember it. By the way, this makes Java different from some other OOP languages. For example, C++ supports multiple inheritance. Everything is more or less clear with inheritance. Let's move on.

Composition and aggregation

Classes and objects can be linked together. Inheritance describes an "is-a" relationship. A lion is an animal. Such a relationship is easily expressed using inheritance, where Animal is the parent class and Lion is the child. However, not all relationships are described this way. For example, a keyboard is definitely related to a computer, but it is not a computer. Hands are somehow related to a person, but they are not a person. In these cases, we have another type of relationship: not "is-a", but "has-a". A hand is not a person, but is part of a person. A keyboard is not a computer, but is part of a computer. A has-a relationship can be described in code using composition and aggregation. The difference lies in the "strictness" of the relationship. Let's give a simple example: We have a Car class. Every car has an engine. Additionally, every car has passengers. What's the fundamental difference between the Engine engine and Passenger[] passengers fields? The fact that passenger A is sitting in a car does not mean that passengers B and C aren't in the car. A car can correspond to multiple passengers. What's more, if all the passengers get out of a car, it will still function smoothly. The relationship between the Car class and the Passenger[] passengers array is less strict. It's called aggregation. It provides another good example of aggregation. Suppose we have a Student class and a StudentGroup class. A student can join multiple student organizations: a physics club, a Star Wars fan club, and/or a student comedy club. Composition is a stricter sort of relationship. When using composition, an object is part of some object and cannot belong to another object of the same type. The simplest example is a car engine. An engine is part of a car and cannot be part of another car. As you can see, their relationship is much stricter than the relationship between Car and Passengers. Relationships between classes. Inheritance, composition, and aggregation - 4
Comments (22)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Anonymous #10428383 Level 12, Seattle, United States
21 January 2024
F1Car object is missing a constructor and assigment
LIMBO Level 32, Estonia
29 May 2023
👍
Aldo Luna Bueno Level 28, Peru
22 February 2022
Awesome explanation!
Stanislav Mayer Level 15, Czech Republic
13 February 2022
"What's more, if all the passengers get out of a car, it will still function smoothly. " Does the same apply to the (Composition) engine?
To be brave #10900452 Level 14, Пекин, China
21 January 2022
组合和聚合(Association, Composition and Aggregation in Java)
TaoLu Level 20, 泾县, China
11 March 2021
Aggregation 聚合关系 Composition 组合关系
Chang You Level 47, Santa Rosa, United States
24 December 2020
Association
2 August 2020
Good explanation, such an easy reading!
Sela Level 20, Poland
12 July 2020
in aggregation lifecycles of objects are not tied to each other as opposed to composition
Jimbo Level 20, Shenzhen
24 June 2020
Awesome