Overview
Class diagrams in Sirena represent the structure of object-oriented systems by showing classes, their attributes, methods, and the relationships between them. They are fundamental for documenting software architecture and design patterns.
Class diagrams are useful for:
-
Documenting object-oriented system architecture
-
Showing inheritance hierarchies
-
Illustrating design patterns
-
Mapping domain models
-
Visualizing database schemas as objects
-
Planning software structure before implementation
Syntax specification
Diagram declaration
Class diagrams are declared using the classDiagram keyword:
classDiagram
<diagram-content>
Attributes
Attributes (fields) are defined with visibility, type, and name:
class ClassName {
+public attribute
-private attribute
#protected attribute
~package attribute
}
Visibility modifiers:
| Symbol | Visibility | Description |
|---|---|---|
|
Public |
Accessible from anywhere |
|
Private |
Accessible only within the class |
|
Protected |
Accessible within the class and subclasses |
|
Package/Internal |
Accessible within the same package |
Full attribute syntax:
visibility type name
Example:
class Animal {
+String name
-int age
#bool isAlive
}
Methods
Methods are defined similarly to attributes but with parentheses:
class ClassName {
+returnType methodName()
+returnType methodName(paramType param)
}
Examples:
class Animal {
+void makeSound()
+void eat(Food food)
+String getName()
}
Relationships
Class diagrams support various relationship types:
| Syntax | Relationship | Description |
|---|---|---|
|
Inheritance |
ClassB inherits from ClassA |
|
Composition |
ClassA is composed of ClassB (strong ownership) |
|
Aggregation |
ClassA contains ClassB (weak ownership) |
|
Association |
ClassA is associated with ClassB |
|
Link (solid) |
General connection between classes |
|
Dependency |
ClassA depends on ClassB |
|
Realization |
ClassA realizes interface ClassB |
|
Composition (dotted) |
Alternative composition syntax |
Cardinality
Relationships can specify cardinality (multiplicity):
ClassA "1" --> "*" ClassB
ClassA "1..*" --> "0..1" ClassB
Common cardinality notations:
-
1- Exactly one -
0..1- Zero or one -
or0..- Zero or more -
1..*- One or more -
n- Exactly n (specific number) -
n..m- Between n and m
Generics
Generic types can be specified using tilde notation:
class List~T~ {
+T get(int index)
+void add(T item)
}
Abstract classes and interfaces
Abstract classes
Abstract classes are indicated with [abstract] stereotype or italics:
class AbstractClass {
<<abstract>>
+abstractMethod()*
}
Interfaces
Interfaces are indicated with [interface] stereotype:
class IInterface {
<<interface>>
+method()
}
Examples
Basic class
classDiagram
class Animal {
+String name
+int age
+makeSound() void
}
This creates a simple class with attributes and a method.
Inheritance hierarchy
classDiagram
class Animal {
+String name
+int age
+String species
+makeSound() void
+eat(food Food) void
+sleep() void
}
class Mammal {
+String furColor
+bool warmBlooded
+giveBirth() void
}
class Bird {
+bool canFly
+String featherColor
+layEggs() void
}
Animal <|-- Mammal
Animal <|-- Bird
This example demonstrates:
-
Base class with common attributes and methods
-
Specialized subclasses
-
Inheritance relationships using
<|--
Complex inheritance with multiple levels
classDiagram
class Animal {
+String name
+int age
+String species
+makeSound() void
+eat(food Food) void
+sleep() void
}
class Mammal {
+String furColor
+bool warmBlooded
+giveBirth() void
}
class Bird {
+bool canFly
+String featherColor
+layEggs() void
}
class Dog {
+String breed
+bark() void
+fetch(item Item) void
}
class Cat {
+bool indoor
+int lives
+meow() void
+purr() void
}
class Eagle {
+float wingSpan
+hunt() void
+soar() void
}
class Penguin {
+swim() void
+slide() void
}
Animal <|-- Mammal
Animal <|-- Bird
Mammal <|-- Dog
Mammal <|-- Cat
Bird <|-- Eagle
Bird <|-- Penguin
This shows:
-
Multi-level inheritance hierarchy
-
Multiple subclasses at each level
-
Common ancestor class
-
Specialized behaviors in leaf classes
Associations and ownership
classDiagram
class Owner {
+String name
+String address
+List~Animal~ pets
+adoptPet(pet Animal) void
}
class Animal {
+String name
+int age
+makeSound() void
}
Owner "1" --> "*" Animal : owns
This demonstrates:
-
Association between classes
-
Cardinality (one-to-many relationship)
-
Relationship label ("owns")
-
Generic type notation
ListAnimal
Composition and aggregation
classDiagram
class University {
+String name
+String location
}
class Department {
+String name
+String head
}
class Professor {
+String name
+String specialization
}
class Student {
+String name
+int studentId
}
class Course {
+String code
+String title
+int credits
}
University *-- Department : contains
Department o-- Professor : employs
Department --> Course : offers
Professor --> Course : teaches
Student --> Course : enrolls in
This shows:
-
Composition (
*--) - departments are part of university -
Aggregation (
o--) - professors work for departments but can exist independently -
Associations (
-→) - various relationships between entities
Interface implementation
classDiagram
class Drawable {
<<interface>>
+draw() void
+resize(width int, height int) void
}
class Shape {
<<abstract>>
+color String
+getArea() float*
}
class Circle {
+radius float
+getArea() float
+draw() void
+resize(width int, height int) void
}
class Rectangle {
+width float
+height float
+getArea() float
+draw() void
+resize(width int, height int) void
}
Drawable <|.. Circle
Drawable <|.. Rectangle
Shape <|-- Circle
Shape <|-- Rectangle
This demonstrates:
-
Interface definition with
[interface] -
Abstract class with
[abstract] -
Interface realization using
<|.. -
Multiple inheritance (from abstract class and interface)
Generic types
classDiagram
class Collection~T~ {
<<interface>>
+add(item T) void
+remove(item T) void
+get(index int) T
}
class List~T~ {
+items T[]
+add(item T) void
+remove(item T) void
+get(index int) T
}
class Map~K,V~ {
+put(key K, value V) void
+get(key K) V
+remove(key K) void
}
Collection~T~ <|.. List~T~
This shows:
-
Generic type parameters with tilde notation
-
Single type parameter
T -
Multiple type parameters
K,V -
Generic interface and implementations
Complete domain model
classDiagram
class Customer {
+int id
+String name
+String email
+List~Order~ orders
+placeOrder(order Order) void
}
class Order {
+int id
+Date orderDate
+OrderStatus status
+List~OrderItem~ items
+float totalAmount
+calculateTotal() float
}
class OrderItem {
+int quantity
+float price
+Product product
+getSubtotal() float
}
class Product {
+int id
+String name
+String description
+float price
+int stockQuantity
}
class OrderStatus {
<<enumeration>>
PENDING
PROCESSING
SHIPPED
DELIVERED
CANCELLED
}
class Payment {
+int id
+float amount
+Date paymentDate
+PaymentMethod method
+processPayment() bool
}
Customer "1" --> "*" Order : places
Order "1" *-- "*" OrderItem : contains
OrderItem "*" --> "1" Product : references
Order "1" --> "1" Payment : paid by
Order --> OrderStatus : has
This comprehensive example includes:
-
Multiple related classes
-
Composition relationships
-
Associations with cardinality
-
Enumeration type
-
Business logic methods
-
Complete domain model structure
Features
Method parameters
Methods can have typed parameters:
class Calculator {
+add(a int, b int) int
+divide(dividend float, divisor float) float
}
Multiple methods and attributes
Classes can have any number of attributes and methods:
class ComplexClass {
+String attr1
+int attr2
-bool attr3
+method1() void
+method2(param String) int
-privateMethod() void
}
Limitations
Best practices
Keep classes focused
Follow the Single Responsibility Principle:
%% Good - focused class
class UserRepository {
+findById(id int) User
+save(user User) void
+delete(id int) void
}
%% Less ideal - too many responsibilities
class UserManager {
+validateUser() bool
+saveToDatabase() void
+sendEmail() void
+generateReport() void
+logActivity() void
}
Use meaningful names
Choose descriptive names for classes, attributes, and methods:
%% Good
class CustomerOrder {
+orderDate Date
+calculateTotal() float
}
%% Less clear
class CO {
+dt Date
+calc() float
}
Show relevant details
Include only the details necessary for the diagram’s purpose:
%% For architecture overview - show only key methods
class UserService {
+createUser(data UserData) User
+authenticateUser(credentials Credentials) Session
}
%% For detailed implementation - show all methods
class UserService {
+createUser(data UserData) User
+authenticateUser(credentials Credentials) Session
-validateUserData(data UserData) bool
-hashPassword(password String) String
-sendWelcomeEmail(user User) void
}
Group related classes
Use inheritance and composition to show relationships:
classDiagram
class Animal
class Mammal
class Reptile
Animal <|-- Mammal
Animal <|-- Reptile
Use appropriate relationship types
Choose the correct relationship type for the situation:
-
Use inheritance (
<|--) for "is-a" relationships -
Use composition (
*--) for "part-of" relationships with strong ownership -
Use aggregation (
o--) for "has-a" relationships with weak ownership -
Use association (
-→) for general relationships