To put it succinctly, a UML Class Diagram represents the classes and the associations between the classes in an object-oriented program. Each class is represented by a separate box, and the associations between classes by arrows. The intent of the class diagram is to represent the complete structure (but not behavior) of an object-oriented program. This allows individual programmers to focus only a small part of the overall program - a class and the classes it has associations with. Combined with the other information contained in the design document, the programmer can implement their piece of the program and it should ‘just work’ when combined with the code written by other programmers.
classDiagram Bear <|-- AnimatedBear class Bear{ <<abstract>> +name string growl()* string } class AnimatedBear{ +growl() string +dance() }
Visibility
In a UML class diagram, visibility (public/protected/private) is specified with symbols:
- $\texttt{+}$ indicates public
- $\texttt{-}$ indicates private
- $\texttt{#}$ indicates protected
Classes
The boxes representing a class are divided into three compartments. The first compartment displays the class identity, the second its attributes (fields), and the third its operations (methods).
Each element in a compartment appears in its own line, and uses the format described below.
Class Identity
The class identity is its name (again, capitalization matters). We can optionally preface it with a visibility symbol (if unmarked, we assume public). If the class is abstract, it should be italicized, and if it is static, it should be underlined.
Class Attributes
The attributes represent the state of the objects, i.e. its variables. These may use different names based on what programming language you are modeling (i.e. fields, properties, instance variables), but if it holds state, this is where it goes. These are represented by typed elements using the pattern:
$$[visibility] name : type [constraint]$$The optional $[visibility]$ details the visibility of the element using the symbols described above.
The $name$ is the element’s name, and should be exact (i.e. capitalization matters). If the element is abstract, its name should be italicized. If it is static, the name should be underlined.
The $type$ is the element’s type (i.e. float/int/bool).
Finally, the $[constraint]$ any optional constraints, expressed in a pair of curly braces after the element.
For example:
$$+ weight: int \{weight: >= 0\}$$Indicates a public field named weight
of type int
whose value should be zero or greater.
Class Operators
The operators represent the behavior of the object, i.e. its methods. These are specified using the format:
$$visibility name([parameter list]) : [return type]$$The $visibility$ details the visibility of the operator (i.e. public/private/protected). Visibility is expressed using symbols described above.
The $name$ is the operator’s name, and should be exact (i.e. capitalization matters). If the operator is abstract, its name should be italicized. If it is static, the name should be underlined.
The $[parameter list]$ is a comma-delineated list of operators in the form:
$$name: type$$Finally, the $[return type]$ is the element’s type (i.e. float/int/bool). If it can be omitted if the return type is void or undefined.
Associations
The association (the relationship) between classes are specified by arrows between the class boxes. The format of the arrow, along with its direction, conveys details about the association.
Associations are classified as being has-a or is-a and weak or strong. The four combinations are therefore:
Association | Type | Representation |
---|---|---|
Realization | weak is-a | dashed arrow |
Generalization | strong is-a | solid arrow |
Aggregation | weak has-a | open diamond fletching |
Composition | strong has-a | filled diamond fletching |
The arrow is always in the direction of the relationship, i.e. from the class that has-a instance of the other class to that class, and from the class that is-a instance of another class to that class.
Realization (Weak is-a)
Realization makes an interface or abstract class “real” by implementing its methods. We call this weak because the interface or abstract class does not provide functionality to the implementing class.
Generalization (Strong is-a)
Generalization refers to extracting the parts that classes have in common and “generalizing” them into a base class. You probably know this relationship as inheritance. We call this a strong relationship because the base class provides functionality to the derived class.
Aggregation (Weak has-a)
Aggregation refers to one class holding references to another one - i.e. through a field of that type, or a collection of that type. It is a weak association because the object the aggregated object or objects can be swapped for other instances (or left null).
Composition (Strong has-a)
Composition also refers to one class holding references to another one. The difference is that with composition, those other object instances are typically created at the same time as the containing object, and are never swapped out for other instances. You can think of the whole group as a single object, even though it is multiple separate ones.
Stereotypes
UML was intended to represent a generic object-oriented language. However, it was recognized that many languages have specific features not found in others. To allow UML to represent these, it also includes the idea of stereotypes - specifying language-specific features using a pair of angled brackets:
$$\langle\langle stereotype \rangle\rangle$$For example, in C# properties are accessor methods (a get and/or set) which are treated as fields. We can represent this by applying a stereotype to a field, i.e.:
$$+Count:int \langle\langle get \rangle\rangle$$Indicates the property Count
has a get
but no set
method.
You can learn more about UML class diagrams by reviewing the CIS 400 textbook, visiting the official UML website, or by reading some of the textbooks in the O'Riley For Higher Education library.