UML Class Diagrams

IB Syllabus: B3.1 – Design and interpret UML class diagrams showing class structure and relationships.


Key Concepts

What is UML?

UML (Unified Modeling Language) is a standard visual language for designing and documenting software systems. A UML class diagram shows the structure of a class – its name, attributes, and methods – in a three-section box.

Class diagrams are drawn BEFORE writing code. They serve as a blueprint that communicates the design to other developers (or to yourself) without getting lost in syntax details.

The Three-Section Box

Every class is represented as a rectangle divided into three sections:

+---------------------------+
|       ClassName           |    ← Section 1: Class name (centred, bold)
+---------------------------+
| - attribute1: Type        |    ← Section 2: Attributes (name: type)
| - attribute2: Type        |
+---------------------------+
| + method1(params): Return |    ← Section 3: Methods (name(params): return)
| + method2(): void         |
+---------------------------+

Access Modifier Symbols

UML uses symbols instead of Java keywords to show visibility:

Symbol Java keyword Meaning
- private Only accessible within the class
+ public Accessible from any class
# protected Accessible within the class and subclasses

Every attribute and method in a UML diagram must have an access modifier symbol. In IB exams, missing symbols lose marks. The standard pattern: - for attributes, + for constructors and public methods.

Attribute Format

Attributes follow the format: visibility name: type

- owner: String
- balance: double
- isActive: boolean
- items: Product[]

Note: the type comes AFTER the name, separated by a colon. This is the opposite of Java syntax (String owner in Java vs owner: String in UML).

Method Format

Methods follow the format: visibility name(parameterTypes): returnType

+ BankAccount(String, double)          ← constructor (no return type)
+ getBalance(): double                 ← getter returns double
+ deposit(double): void                ← mutator returns void
+ canWithdraw(double): boolean         ← method returns boolean

Constructors are listed with the class name and parameter types but no return type.

Complete Example

Java class:

public class BankAccount {
    private String owner;
    private double balance;

    public BankAccount(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

    public String getOwner() { return owner; }
    public double getBalance() { return balance; }
    public void deposit(double amount) { ... }
    public boolean canWithdraw(double amount) { ... }
}

UML diagram:

classDiagram
    class BankAccount {
        -owner : String
        -balance : double
        +BankAccount(String, double)
        +getOwner() String
        +getBalance() double
        +deposit(double) void
        +canWithdraw(double) boolean
    }

Relationship Arrows

UML diagrams also show how classes relate to each other.

Inheritance (is-a) – solid line with a closed triangle pointing to the parent:

classDiagram
    Animal <|-- Dog
    class Animal
    class Dog

Read as: “Dog IS-A Animal” – Dog extends Animal.

Aggregation (has-a) – line with an open diamond on the “whole” side:

classDiagram
    Student o-- Address
    class Student
    class Address

Read as: “Student HAS-A Address” – Student contains an Address object as an attribute.

Both in one diagram:

classDiagram
    Vehicle <|-- Car
    Car o-- Engine
    class Vehicle
    class Car
    class Engine

Car IS-A Vehicle (inheritance) and Car HAS-A Engine (aggregation).

Drawing from Code

To convert Java code to UML:

  1. Class name goes in section 1
  2. Instance variables become attributes in section 2 (add - for private, + for public)
  3. Constructors and methods go in section 3 (add + for public, - for private)
  4. Flip the type order: String name in Java becomes name: String in UML
  5. Add return types after a colon: void, String, int, boolean, etc.

Drawing from a Scenario

To convert a scenario description to UML:

  1. Identify the nouns – these become classes or attributes
  2. Identify the verbs – these become methods
  3. Identify relationships – “has a” suggests aggregation, “is a” suggests inheritance
  4. Decide data types for each attribute
  5. Decide return types and parameters for each method

In exams, UML diagrams typically carry 2-5 marks. Marks are awarded for: correct class box with three sections [1], correct attributes with types and visibility [1], correct methods with return types [1], correct relationship arrows [1].


Worked Examples

Example 1: Code to UML

Java code:

public class Product {
    private String name;
    private double price;
    private int stock;

    public Product(String name, double price, int stock) { ... }
    public String getName() { return name; }
    public double getPrice() { return price; }
    public int getStock() { return stock; }
    public boolean isInStock() { return stock > 0; }
    public void sell(int quantity) { ... }
    private boolean hasEnoughStock(int quantity) { ... }
}

UML:

classDiagram
    class Product {
        -name : String
        -price : double
        -stock : int
        +Product(String, double, int)
        +getName() String
        +getPrice() double
        +getStock() int
        +isInStock() boolean
        +sell(int) void
        -hasEnoughStock(int) boolean
    }

Notice: hasEnoughStock is - (private) because it is a helper method.

Example 2: Scenario to UML

Scenario: A school library tracks books. Each book has a title, author, ISBN, and whether it is currently on loan. The library can check out and return books.

Step 1: Nouns = Book (class), title, author, ISBN, onLoan (attributes)

Step 2: Verbs = checkOut, returnBook (methods). Also need getters.

Step 3: Data types: title (String), author (String), ISBN (String), onLoan (boolean)

UML:

classDiagram
    class Book {
        -title : String
        -author : String
        -isbn : String
        -onLoan : boolean
        +Book(String, String, String)
        +getTitle() String
        +getAuthor() String
        +isOnLoan() boolean
        +checkOut() void
        +returnBook() void
    }

Example 3: Two Classes with Relationship

Scenario: A Library manages an array of Book objects.

classDiagram
    class Library {
        -books : Book[]
        -name : String
        +Library(String, int)
        +addBook(Book) void
        +findByTitle(String) Book
        +countAvailable() int
    }
    class Book {
        -title : String
        -author : String
        -onLoan : boolean
        +Book(String, String)
        +getTitle() String
        +isOnLoan() boolean
        +checkOut() void
    }
    Library o-- Book

The diamond (◇) on the Library side shows aggregation: Library HAS Books.


Quick Check

Q1. How is a private double balance written in UML?

Q2. What are the three sections of a UML class diagram?

Q3. Which UML symbol represents inheritance?

Q4. How does a constructor differ from a method in a UML diagram?

Q5. A School contains an array of Student objects. Which UML relationship is this?


Fill in the Blanks

Complete the UML notation rules:

UML Access Modifier Symbols
============================
 means private
 means public
 means protected

UML Attribute Format
====================
visibility  : 

UML Relationships
=================
△ (closed triangle) = 
◇ (open diamond) = 

Spot the Error

This UML diagram has a notation error. Click the line with the error, then pick the fix.

1+---------------------------+
2|        Student            |
3+---------------------------+
4| - String: name            |
5| - grade: int              |
6+---------------------------+
7| + getName(): String       |
8+---------------------------+

Pick the correct UML format:


Practice Exercises

Core

  1. Code to UML – Convert this Java class to a complete UML class diagram:
    public class Circle {
        private double radius;
        public Circle(double radius) { this.radius = radius; }
        public double getRadius() { return radius; }
        public double getArea() { return Math.PI * radius * radius; }
        public void setRadius(double radius) { if (radius > 0) this.radius = radius; }
    }
    
  2. Scenario to UML – A vet clinic tracks patients. Each patient has a name (String), species (String), age (int), and vaccination status (boolean). The clinic can vaccinate a patient and check if it is vaccinated. Draw the UML diagram.

  3. Read a UML diagram – Given this UML, write the Java class:

    classDiagram
        class Song {
            -title : String
            -artist : String
            -durationSecs : int
            +Song(String, String, int)
            +getTitle() String
            +getArtist() String
            +isLong() boolean
        }
    

Extension

  1. Two-class diagram – Draw UML for a Playlist that contains an array of Song objects. Show both classes and the aggregation relationship. The playlist has a name and can add songs, remove by title, and get the total duration.

  2. Identify relationships – For each pair, state whether the relationship is inheritance (is-a) or aggregation (has-a):

    • (a) Car and Engine
    • (b) Dog and Animal
    • (c) School and Student
    • (d) SavingsAccount and BankAccount

Challenge

  1. Full system design – A hospital needs to track doctors and appointments. Each doctor has a name, specialisation, and a list of appointments. Each appointment has a patient name, date, and duration. Draw the complete UML with both classes, their attributes, methods, and the relationship between them.

Connections

  • Prerequisites: Encapsulation – UML - and + symbols represent the private/public access modifiers
  • Prerequisites: Access Modifiers – understanding what each visibility level means
  • Next: Aggregation – deeper dive into the has-a relationship shown with ◇
  • Forward: Inheritance – the is-a relationship shown with △

© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.