UML Class Diagrams 101: The Beginner's Guide
A gentle introduction to UML class diagrams. Learn the class box, visibility markers, attribute and method syntax, and the five arrow types (association, inheritance, composition, aggregation, dependency). Build a complete library-system diagram step by step, with an illustration for every idea.
Palakorn V.
Product Lead
What Is a Class Diagram?
A class diagram is a picture of the types in your program. Not the individual values — those come and go — but the stable shapes that every value fits into: a User, an Order, a Document. Each of those types has its own data and its own behaviours, and each connects to other types in specific ways. A class diagram lays those types, their data, their behaviours, and their connections out as a single picture.
Here is a minimal one. Three classes, two relationships, and enough information to have a genuine design conversation about a library system:
Member borrows Books; both belong to a Library. Each class has its own data (above the line) and behaviour (below the line).That picture encodes a surprising amount of information. It tells you which objects exist, what each one remembers, what each one can do, and how many of one type relate to how many of another. A fluent reader extracts all of that in about ten seconds. This article teaches you to read and draw class diagrams that fluently — from scratch, assuming no background in UML or object-oriented programming.
What Is a "Class", Really?
If the word "class" is new to you, here's a one-paragraph introduction. In programming, a class is a template for a kind of thing. "User" is a class; "Alice, age 32, email alice@example.com" is one instance of that class. The class defines what every user has (an email, a name, a join date) and what every user can do (log in, change their password). Individual users are created from the template. Even if you have never written a line of object-oriented code, you can use a class diagram as a data-modelling tool; the shapes and arrows are worth knowing whether or not you ever open a code editor.
A class has two sides: its data (what it knows, called attributes or fields) and its behaviour (what it can do, called methods or operations). The class diagram puts both sides on the picture, in separate compartments, so a reader can see at a glance what a given class is shaped like.
The Class Box: Three Compartments
Every class in a UML class diagram is drawn as a rectangle with three horizontal compartments. The top compartment holds the class name. The middle holds the attributes. The bottom holds the methods. Two dividing lines separate them.
You can leave compartments out when they add no information — a very simple class with nothing worth saying in the bottom compartment is often drawn as just a name-plus-attributes box, and an abstract role marker might be drawn as a single-compartment rectangle with just a name. But in most diagrams you'll want all three.
A convention you'll see often: the class name in bold. If the class is abstract (it's a template that can't be instantiated directly — you must subclass it), the name is written in italics. Don't worry about abstract classes for now; they're a detail you pick up once you know the basics.
Visibility: The Four Symbols Before Each Member
Each attribute and method starts with a visibility marker — a single character that shows who is allowed to touch that member. You'll see four of them:
+public — anyone can use it.-private — only the class itself can use it. Used for implementation details you don't want leaking out.#protected — the class and its subclasses can use it. A rarer middle ground.~package-private — anyone in the same package can use it. Mostly a Java thing.
Don't skip the visibility marker. A + on a method is a promise that the method is part of the public API. A - is a promise that the caller doesn't need to worry about it. Promises are the whole point of a class diagram.
How to Write Attributes and Methods
Attributes follow the pattern visibility name: type = default. The type and default are optional, but writing them is almost always worth it — they make the class self-documenting.
+ id: UUID+ createdAt: DateTime = now()- loginAttempts: int = 0
Methods follow a similar pattern: visibility name(parameters): returnType. Parameters are comma-separated, each with its own name and type.
+ login(password: string): bool+ resetPassword(email: string, token: string): void- hash(input: string): string
You don't always need every detail. For early-stage diagrams, dropping the types and keeping just names and visibility works fine. For diagrams you'll review with engineers, add the types — they make the class a contract rather than a sketch.
Relationships Between Classes
Classes don't live alone. They hold references to each other, extend each other, use each other. UML uses five different line styles to express the different ways two classes can connect. Each style has a specific meaning, and getting them right is what separates a useful diagram from decoration.
Let's go through each one in plain English.
Association: "uses" or "has a"
A plain solid line with no adornments. It means "these two classes have some sort of long-lived relationship". A User has an Address. A Car has an Engine. A Document has Comments. Nothing more specific. Start here when you're not yet sure which of the stronger relationships fits — it's the safe default.
Inheritance: "is a"
A solid line with a hollow triangle pointing at the parent class. It means the child is a specialized version of the parent: Dog is an Animal, AdminUser is a User, ElectricCar is a Car. The child inherits everything from the parent — the parent's attributes and methods are automatically available on the child — and usually adds some of its own.
Dog and Cat both inherit from Animal — every dog and cat has a name and can eat(). The italic on Animal marks it as abstract.Composition vs. Aggregation: Two Flavours of "Has"
Both composition and aggregation describe a "whole-part" relationship — one class contains another. The difference is ownership of lifecycle.
- Composition (filled diamond): the container owns the parts. When the container is destroyed, the parts go with it. A
HousecontainsRooms — tear down the house, the rooms are gone. The filled diamond sits on the container's side. - Aggregation (hollow diamond): the container has the parts, but doesn't own their lifecycle. A
TeamhasPlayers, but destroying the team doesn't destroy the players — they can join another team. The hollow diamond sits on the container's side.
Both diamonds sit on the container's side of the line. A useful test: "If I destroy the whole, do the parts also get destroyed?" Yes → filled diamond. No → hollow diamond.
Dependency and Realization: The Dashed Lines
Dashed lines are for weaker, less permanent connections.
- Dependency (dashed line with open arrow): "class A knows about class B, but only briefly" — a parameter type in a method, a short-lived local variable. "When this method runs, it needs a
Logger." Dependencies are fleeting. - Realization (dashed line with hollow triangle): "class A implements interface B". Like inheritance, but specifically for interfaces — an interface is a contract with no implementation, and a class that "realizes" it promises to fulfil that contract.
You'll see dependency a lot once you start looking for it. It's the "I use this type for a second" relationship — not worth a solid line, but worth showing on a detailed diagram.
Multiplicity: Counting the Connections
When two classes are connected, you often need to say how many of each. UML uses small numeric labels near each end of the line. The most common patterns:
1— exactly one.0..1— zero or one (optional).*(or0..*) — zero or many.1..*— one or many (at least one).5..10— a specific range.
A User has 1 primary Address but * comments. A Team has 5..15 players. A Document has 1..* versions (every document has at least the initial version). Place the label right next to the line's endpoint on the side it describes.
Worked Example: A Library System
Time to pull everything together. Let's model a small library. A library has books. Members can borrow books. Staff are a special kind of member with extra privileges. Books come in two flavours — physical books and e-books — which share most of their behaviour.
Library composes Books (filled diamond — destroy the library, the books go too). Book is abstract, with PhysicalBook and EBook as concrete subclasses. StaffMember extends Member. A Member aggregates the Books they've borrowed (hollow diamond — those books exist independently of the member).Reading top-down, this diagram captures the entire shape of the library system in one picture: a new developer could look at it and know which classes to build, which classes extend which, and how the objects connect at runtime. That's the goal of every class diagram.
Common Beginner Mistakes
Six mistakes show up in almost every first class diagram.
- Skipping visibility markers. "
id: UUID" instead of "+ id: UUID". The marker is part of the contract — without it, the reader doesn't know whether the attribute is public API or internal detail. - Using inheritance for "has-a" relationships. A
Carhas anEngine; it is not anEngine. Inheritance means "is a", not "has a". When in doubt, try the sentence out loud — if it sounds wrong, use an association or composition instead. - Confusing composition with aggregation. The filled diamond means "I control my parts' lifecycle". If the parts can survive the whole, you want a hollow diamond. Always ask "what happens to the parts if I delete the whole?"
- Leaving off multiplicity. "User connects to Address" is vague. "User has exactly one Address" and "User has zero or many Addresses" are different databases. Without the multiplicity numbers, the diagram can't distinguish.
- Over-loading the diagram. A class diagram with thirty classes and every method shown is unreadable. Pick a bounded context — "auth", "billing", "search" — and draw a separate diagram for each. Tie them together with a higher-level package or component diagram if needed.
- Drawing the arrow in the wrong direction. Inheritance points from child to parent. Association can be directional (arrow on one end) or not (no arrows). Composition/aggregation diamond always sits on the owner's side. Getting these backwards flips the meaning entirely — double-check before finalizing.
Where to Go Next
Class diagrams are the gateway drug of UML. Once you can draw one, three related diagrams are worth learning next:
- Object diagrams show instances of your classes at a specific moment — useful for walking through a concrete scenario.
- Sequence diagrams show how methods call each other over time — the "who talks to whom and in what order" view.
- Component diagrams zoom out one level, showing how groups of classes get packaged into deployable chunks.
The class diagram also translates almost one-to-one into object-oriented code. One class becomes one file, attributes become fields, methods become methods, and inheritance turns into a language keyword (extends, inherits, : ParentName). Practise translating a diagram to code and back a few times, and the notation becomes second nature.
A Note on Tools
Class diagrams are a notation. You can draw them cleanly on paper, on a whiteboard, in PowerPoint, or in any dedicated tool. If you'd like a tool with pre-built UML shapes (class boxes with compartments already divided, all the arrow styles in one picker, Mermaid classDiagram import for turning a text sketch into polished shapes), CorriDraw — the tool you're reading this on — is one option. The ideas transfer: you now know how to read and draw a class diagram anywhere.
More from the blog .
Ready to start collaborating ?
Join thousands of teams using CorriDraw for their visual collaboration needs.