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.

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.
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).

Let's watch a short video that clarifies this important difference.
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. Theocreates 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:
- The platform has
Courses. ACourseis made up of one or moreModules. AModulecannot exist without aCourse. - Each
Moduleis made up of one or moreLessons. ALessoncannot exist without aModule. - There are two types of lessons:
VideoLessonandTextLesson. Both are specific kinds ofLesson. - A
Studentcan be enrolled in multipleCourses. ACoursecan have manyStudents. TheStudentandCourseentities 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 (
*--):CoursetoModuleandModuletoLessonare composition because their parts (Modules, Lessons) are intrinsically tied to the whole and their lifecycles are dependent. - Aggregation (
o--):StudenttoCourseis aggregation because both can exist independently. Deleting aCoursedoesn't delete theStudent, and vice-versa. - Inheritance (
<|--):VideoLessonandTextLessonboth "are-a" type ofLesson, so they inherit from it. We've markedLessonas 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