Understanding Object-Oriented Relationships: Inheritance, Association, Composition, and Aggregation

Introduction

Muhammad Humza Khan
3 min readOct 14, 2023

Object-oriented programming (OOP) is a powerful paradigm for designing and structuring code. At its core, OOP relies on four fundamental relationships between classes: Inheritance, Association, Composition, and Aggregation. These relationships help us model complex systems and facilitate the creation of robust, maintainable, and scalable software.

In this article, we will explore each of these relationships, providing a clear understanding of when and how to use them in your software design.

Inheritance

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a new class to inherit the properties and behaviors of an existing class. It represents an "is-a" relationship and promotes code reuse. Here's an example:

open class Animal(val name: String) {
fun speak() {
println("$name makes a sound.")
}
}

class Dog(name: String, val breed: String) : Animal(name) {
fun bark() {
println("$name, the $breed, barks loudly.")
}
}

In this example, we have an Animal base class with a name property and a speak() method. The Dog class inherits from Animal and adds a breed property and a bark() method.

Association

Association is a relationship between classes where each class has an independent existence, and they are loosely connected. It is often used to represent a simple connection between objects. Here's an example:

class Student(val name: String)

class Course(val title: String)

val student1 = Student("Alice")
val course1 = Course("Mathematics")
student1.courses = listOf(course1)

In this example, a Student class and a Course class have an association. A Student can enroll in multiple courses, but the two classes are independent entities.

Composition

Composition represents a strong relationship where one class is composed of other classes, and the parts are essential to the existence of the whole. It's used to create complex objects by combining simpler ones. Here's an example:

class Engine {
fun start() {
println("Engine started.")
}
}

class Car {
private val engine = Engine()

fun drive() {
engine.start()
println("Car is moving.")
}
}

In this example, the Car class is composed of an Engine. The Car cannot function without the Engine, and the Engine is encapsulated within the Car.

Aggregation

Aggregation is a weaker relationship where one class contains other classes, but the parts can exist independently. It is used when parts have a life cycle of their own and can be shared among multiple whole objects. Here's an example:

class Department(val name: String) {
val employees = mutableListOf<Employee>()
}

class Employee(val name: String)

val hrDepartment = Department("HR")
val employee1 = Employee("Alice")
hrDepartment.employees.add(employee1)

In this example, a Department class has an aggregation relationship with the Employee class. Multiple employees can be part of the Department, and each employee can exist independently.

These Kotlin code examples and detailed explanations should provide a comprehensive understanding of Inheritance, Association, Composition, and Aggregation in object-oriented programming. These relationships are crucial for building flexible, maintainable, and modular code in your software applications.

--

--

Muhammad Humza Khan

Mobile App Developer | Android | IOS | Java | Kotlin | Swift | Objective C