Create your own
Lesson illustration

Object-Oriented Relationships: Inheritance, Aggregation, and Composition

Welcome to the third lesson on creating UML class diagrams. In our previous session, you learned how to model the fundamental "uses-a" relationship between classes using associations, enriching them with direction, multiplicity, and role labels. This gave you the tools to map out the basic connections within a software system.

Now, we will move beyond general associations to explore more specific and powerful types of relationships. This lesson focuses on differentiating and encoding three crucial concepts in object-oriented design: inheritance ("is-a"), aggregation (weak "has-a"), and composition (strong "has-a"). Mastering these will enable you to describe the hierarchical and part-whole structures of your system with much greater precision, reflecting common patterns in software development like extension and ownership.

A Visual Guide to Relationships

Before diving into the details, let's look at the standard UML symbols for the relationships we'll cover today, alongside those you've already seen. This legend provides a quick visual reference for the notation.

This image displays the six most common UML relationship symbols. In this lesson, we will focus on Inheritance, Aggregation, and Composition.

Inheritance: The "is-a" Relationship

In object-oriented programming, it's common for different classes to share common characteristics. For instance, in a payment system, CreditCardPayment, PayPalPayment, and BankTransferPayment might all share properties like amount and currency, and methods like execute(). Inheritance allows us to model this by creating a general parent class (or superclass) that child classes (or subclasses) can extend. The child inherits the attributes and operations of the parent, and can also add its own specific features or override parent behaviors. This is known as an "is-a" relationship (e.g., a CreditCardPayment is a Payment).

The following video provides an excellent conceptual overview of inheritance.

UML class diagrams

Watch this segment from the Lucid Software video on UML class diagrams. It explains the core concept of inheritance using a clear analogy.

Focus on the explanation from the start, where the presenter introduces the idea of subclasses inheriting from a superclass and how this is visualized.

In UML, inheritance is shown with a solid line and a hollow, triangular arrowhead pointing from the child to the parent. This direction is crucial—it signifies that the child "is a" type of the parent.

In Mermaid, the syntax for inheritance is Parent <|-- Child. Notice that the class on the left of the operator is the parent.

The next video demonstrates how to implement this relationship in Mermaid syntax.

Mermaid JS: Finally There's A Great UML & Diagram Drawing Tool

In this clip from ArjanCodes, you'll see how inheritance is coded in a Mermaid class diagram.

Watch the section from the introduction of inheritance to its implementation for both Customer and PaymentProcessor classes. Pay attention to the PaymentProcessor <|-- StripePaymentProcessor syntax.

A common mistake is reversing the direction. Child <|-- Parent would incorrectly state that the parent inherits from the child.

Part-Whole Relationships: Aggregation and Composition

While inheritance models an "is-a" relationship, aggregation and composition model a "has-a" relationship, where one class is a whole and another is a part of that whole. The key distinction between them lies in the lifecycle of the "part" object relative to the "whole."

  • Aggregation is a weak "has-a" relationship. The part can exist independently of the whole.
  • Composition is a strong "has-a" relationship. The part cannot exist without the whole; its lifecycle is bound to it.

The following image provides a classic visual distinction. An Engine is aggregated into a Car (it can be removed and exist on its own), while a Page is composed within a Book (it cannot exist if the book is destroyed).

An example of aggregation, where an Engine is part of a Car, and composition, where a Page is part of a Book.

Let's watch a short video that clarifies this important difference.

UML class diagrams

This segment from the Lucid Software video explains the logic behind aggregation and composition using simple, intuitive examples.

First, watch the explanation of aggregation, where a part can exist outside the whole. Then, continue with the explanation of composition, where the part's lifecycle depends on the whole.

Aggregation (Weak "has-a")

In aggregation, the "whole" class has a reference to the "part" class, but does not own it. For example, a Team has Players, but if the Team is disbanded, the Players still exist and can join other teams.

  • UML Symbol: A solid line with a hollow diamond on the side of the "whole" (the owner/container).
  • Mermaid Syntax: Owner o-- Part. The o creates the hollow diamond.

Composition (Strong "has-a")

In composition, the "whole" class owns the "part" class. This implies lifecycle management. When an instance of the "whole" is created, it may create its parts. When the "whole" is destroyed, its parts are destroyed with it (a cascade delete). A classic example is an Order and its OrderItems. The line items have no meaning and cannot exist without the order they belong to.

  • UML Symbol: A solid line with a filled diamond on the side of the "whole."
  • Mermaid Syntax: Owner *-- Part. The * creates the filled diamond.

This final video demonstrates the Mermaid syntax for both and discusses the subtle but important design choice between them.

Mermaid JS: Finally There's A Great UML & Diagram Drawing Tool

This clip from ArjanCodes shows how to code aggregation and composition in Mermaid and discusses the practical difference in a software context.

Watch the segment from the discussion on the relationship between an Order and a Customer. The presenter explains why aggregation (o--) is appropriate there, and contrasts it with composition (*--) for a Car and Engine.

Reference and Common Pitfalls

Choosing the correct relationship is a critical design decision. Using composition when you mean aggregation can imply incorrect system behavior, such as accidentally deleting data. The following resource provides an excellent summary and highlights common errors.

UML Class Diagrams: Notation, Relationships, Mermaid Syntax | CalibreOS

This article from CalibreOS provides a concise, developer-focused guide to UML relationships. It's a great reference to consolidate what you've learned.

Start by reading the section on relationship types to review the definitions of inheritance, composition, and aggregation. Next, study the table under the section "Complete Mermaid Example: Parking Lot System", starting just above the code block. Focus on the rows for Inheritance, Composition, and Aggregation to see the syntax and examples side-by-side. Finally, and most importantly, carefully read the list of common pitfalls. These tips are invaluable for avoiding frequent mistakes in practice.

Practice Exercise

Now, let's apply these concepts. Imagine you are designing a simple online learning platform. Model the following requirements in a Mermaid class diagram:

  1. The platform has Courses. A Course is made up of one or more Modules. A Module cannot exist without a Course.
  2. Each Module is made up of one or more Lessons. A Lesson cannot exist without a Module.
  3. There are two types of lessons: VideoLesson and TextLesson. Both are specific kinds of Lesson.
  4. A Student can be enrolled in multiple Courses. A Course can have many Students. The Student and Course entities exist independently.

Your diagram should include the following classes: Course, Module, Lesson, VideoLesson, TextLesson, and Student. Use the correct relationship types (inheritance, composition, aggregation) and add multiplicity where appropriate.

Click here to see a possible solution

Explanation of the design choices:

  • Composition (*--): Course to Module and Module to Lesson are composition because their parts (Modules, Lessons) are intrinsically tied to the whole and their lifecycles are dependent.
  • Aggregation (o--): Student to Course is aggregation because both can exist independently. Deleting a Course doesn't delete the Student, and vice-versa.
  • Inheritance (<|--): VideoLesson and TextLesson both "are-a" type of Lesson, so they inherit from it. We've marked Lesson as an abstract class (<<abstract>>) as you would likely only instantiate its concrete children.

Conclusion

In this lesson, you've moved beyond simple associations to model more sophisticated object-oriented structures. You now have the tools to represent hierarchies and ownership, which are fundamental to designing robust and maintainable software.

Here are the key takeaways:

  • Inheritance (<|--): Models an "is-a" relationship, where a child class extends a parent class. The arrow points to the parent.
  • Composition (*--): Models a strong "has-a" relationship where the "part" cannot exist without the "whole." The filled diamond is on the "whole's" side.
  • Aggregation (o--): Models a weak "has-a" relationship where the "part" has an independent lifecycle from the "whole." The hollow diamond is on the "whole's" side.

You have now completed the core topics for modeling object structure with class diagrams. The next module will shift our focus from the application's internal object model to its data persistence layer. You will learn how to create Entity-Relationship (ER) diagrams, a standard way to model the structure of relational databases.

Can't find a good explanation? Sign up and we'll make it for you

Sign up