Terms and Concepts
A classifier is a mechanism that describes structural and behavioral features. Classifiers include classes, associations, interfaces, datatypes, signals, components, nodes, use cases, and subsystems.
Classifiers
When you model, you'll discover abstractions that represent things in the real world and things in your solution. For example, if you are building a Web-based ordering system, the vocabulary of your project will likely include a Customer class (representing people who order products) and a TRansaction class (an implementation artifact, representing an atomic action). In the deployed system, you might have a Pricing component, with instances living on every client node. Each of these abstractions will have instances; separating the essence and the instance of the things in your world is an important part of modeling.
Modeling the vocabulary of a system is discussed in Chapter 4; the class/object dichotomy is discussed in Chapter 2 . |
Some things in the UML don't have instancesfor example, packages and generalization relationships. In general, those modeling elements that can have instances are called classifiers. Even more important, a classifier has structural features (in the form of attributes) as well as behavioral features (in the form of operations). Every instance of a given classifier shares the same feature definitions, but each instance has its own value for each attribute.
Instances are discussed in Chapter 13; packages are discussed in Chapter 12; generalization is discussed in Chapters 5 and 10; associations are discussed in Chapters 5 and 10; messages are discussed in Chapter 16; interfaces are discussed in Chapter 11; datatypes are discussed in Chapters 4 and 11; signals are discussed in Chapter 21; components are discussed in Chapter 15; nodes are discussed in Chapter 27; use cases are discussed in Chapter 17; subsystems are discussed in Chapter 32 . |
The most important kind of classifier in the UML is the class. A class is a description of a set of objects that share the same attributes, operations, relationships, and semantics. Classes are not the only kind of classifier, however. The UML provides a number of other kinds of classifiers to help you model.
A collection of operations that are used to specify a service of a class or a component | |
A type whose values are immutable, including primitive built-in types (such as numbers and strings) as well as enumeration types (such as Boolean) | |
A description of a set of links, each of which relates two or more objects. | |
The specification of an asynchronous message communicated between instances | |
A modular part of a system that hides its implementation behind a set of external interfaces | |
A physical element that exists at run time and that represents a computational resource, generally having at least some memory and often processing capability | |
A description of a set of a sequence of actions, including variants, that a system performs that yields an observable result of value to a particular actor | |
A component that represents a major part of a system |
For the most part, every kind of classifier may have both structural and behavioral features. Furthermore, when you model with any of these classifiers, you may use all the advanced features described in this chapter to provide the level of detail you need to capture the meaning of the abstraction.
Graphically, the UML distinguishes among these different classifiers, as Figure 9-2 shows.
Figure 9-2. Classifiers

Note
A minimalist approach would have used one icon for all classifiers; however, a distinctive visual cue was deemed important. Similarly, a maximal approach would have used different icons for each kind of classifier. That doesn't make sense either because, for example, classes and datatypes aren't that different. The design of the UML strikes a balancesome classifiers have their own icon, and others use special keywords (such as type, signal, and subsystem).
Visibility
One of the design details you can specify for an attribute or operation is visibility. The visibility of a feature specifies whether it can be used by other classifiers. In the UML, you can specify any of four levels of visibility.
A classifier can see another classifier if it is in scope and if there is an explicit or implicit relationship to the target; relationships are discussed in Chapters 5 and 10; descendants come from generalization relationships, as discussed in Chapter 5; permission allows a classifier to share its private features, as discussed in Chapter 10 . |
Figure 9-3 shows a mix of public, protected, and private figures for the class Toolbar.
Figure 9-3. Visibility

When you specify the visibility of a classifier's features, you generally want to hide all its implementation details and expose only those features that are necessary to carry out the responsibilities of the abstraction. That's the very basis of information hiding, which is essential to building solid, resilient systems. If you don't explicitly adorn a feature with a visibility symbol, you can usually assume that it is public.
Note
The UML's visibility property matches the semantics common among most programming languages, including C++, Java, Ada, and Eiffel. Note that languages differ slightly in their semantics of visibility, however.
Instance and Static Scope
Another important detail you can specify for a classifier's attributes and operations is scope. The scope of a feature specifies whether each instance of the classifier has its own distinct value of the feature or whether there is just a single value of the feature shared by all instances of the classifier. In the UML, you can specify two kinds of owner scope.
Instances are discussed in Chapter 13 . |
As Figure 9-4 (a simplification of the first figure) shows, a feature that is static scoped is rendered by underlining the feature's name. No adornment means that the feature is instance scoped.
Figure 9-4. Owner Scope

In general, most features of the classifiers you model will be instance scoped. The most common use of static scoped features is for private attributes that must be shared among all instances of a class, such as for generating unique IDs for new instances of a class.
Note
Static scope maps to what C++ and Java call static attributes and operations.
Static scope works somewhat differently for operations. An instance operation has an implicit parameter corresponding to the object being manipulated. A static operation has no such parameter; it behaves like a traditional global procedure that has no target object. Static operations are used for operations that create instances or operations that manipulate static attributes.
Abstract, Leaf, and Polymorphic Elements
You use generalization relationships to model a lattice of classes, with more-generalized abstractions at the top of the hierarchy and more-specific ones at the bottom. Within these hierarchies, it's common to specify that certain classes are abstractmeaning that they may not have any direct instances. In the UML, you specify that a class is abstract by writing its name in italics. For example, as Figure 9-5 shows, Icon, RectangularIcon, and ArbitraryIcon are all abstract classes. By contrast, a concrete class (such as Button and OKButton) may have direct instances.
Figure 9-5. Abstract and Concrete Classes and Operations

Generalization is discussed in Chapters 5 and 10; instances are discussed in Chapter 13 . |
Whenever you use a class, you'll probably want to inherit features from other, more-general classes, and have other, more-specific classes inherit features from it. These are the normal semantics you get from classes in the UML. However, you can also specify that a class may have no children. Such an element is called a leaf class and is specified in the UML by writing the property leaf below the class's name. For example, in the figure, OKButton is a leaf class, so it may have no children.
Operations have similar properties. Typically, an operation is polymorphic, which means that, in a hierarchy of classes, you can specify operations with the same signature at different points in the hierarchy. An operation in a child class overrides the behavior of a similar operation in the parent class. When a message is dispatched at run time, the operation in the hierarchy that is invoked is chosen polymorphically-that is, a match is determined at run time according to the type of the object. For example, display and isInside are both polymorphic operations. Furthermore, the operation
Icon::display() is abstract, meaning that it is incomplete and requires a child to supply an implementation of the operation. In the UML, you specify an abstract operation by writing its name in italics, just as you do for a class. By contrast, Icon::getID() is a leaf operation, so designated by the property leaf. This means that the operation is not polymorphic and may not be overridden. (This is similar to a Java final operation.)
Messages are discussed in Chapter 16 . |
Note
Abstract operations map to what C++ calls pure virtual operations; leaf operations in the UML map to C++ nonvirtual operations.
Multiplicity
Whenever you use a class, it's reasonable to assume that there may be any number of instances of that class (unless, of course, it is an abstract class and may not have any direct instances, although there may be any number of instances of its concrete children). Sometimes, though, you'll want to restrict the number of instances a class may have. Most often, you'll want to specify zero instances (in which case, the class is a utility class that exposes only static-scoped attributes and operations), one instance (a singleton class), a specific number of instances, or many instances (the default case).
Instances are discussed in Chapter 13 . |
The number of instances a class may have is called its multiplicity. Multiplicity is a specification of the range of allowable cardinalities an entity may assume. In the UML, you can specify the multiplicity of a class by writing a multiplicity expression in the upper-right corner of the class icon. For example, in Figure 9-6, NetworkController is a singleton class. Similarly, there are exactly three instances of the class ControlRod in the system. Multiplicity applies to attributes, as well. You can specify the multiplicity of an attribute by writing a suitable expression in brackets just after the attribute name. For example, in the figure, there are two or more consolePort instances in the instance of NetworkController.
Figure 9-6. Multiplicity

Multiplicity applies to associations as well, as discussed in Chapters 5 and 10 . |
Attributes are related to the semantics of association, as discussed in Chapter 10 . |
Note
The multiplicity of a class applies within a given context. There is an implied context for the entire system at the top level. The entire system can be regarded as a structured classifier.
Structured classifiers are discussed in Chapter 15 . |
Attributes
At the most abstract level, when you model a class's structural features (that is, its attributes), you simply write each attribute's name. That's usually enough information for the average reader to understand the intent of your model. As the previous parts have described, however, you can also specify the visibility, scope, and multiplicity of each attribute. There's still more. You can also specify the type, initial value, and changeability of each attribute.
In its full form, the syntax of an attribute in the UML is
You can also use stereotypes to designate sets of related attributes, such as housekeeping attributes, as discussed in Chapter 6 . |
[visibility] name
[':' type] ['[' multiplicity] ']']
['=' initial-value]
[property-string {',' property-string}]
For example, the following are all legal attribute declarations:
Name only | |
Visibility and name | |
Name and type | |
Name, type, and multiplicity | |
Name, type, and initial value | |
Name and property |
Unless otherwise specified, attributes are always changeable. You can use the readonly property to indicate that the attribute's value may not be changed after the object is initialized.
You'll mainly want to use readonly when modeling constants or attributes that are initialized at the creation of an instance and not changed thereafter.
Note
The readonly property maps to const in C++.
Operations
At the most abstract level, when you model a class's behavioral features (that is, its operations and its signals), you will simply write each operation's name. That's usually enough information for the average reader to understand the intent of your model. As the previous parts have described, however, you can also specify the visibility and scope of each operation. There's still more: You can also specify the parameters, return type, concurrency semantics, and other properties of each operation. Collectively, the name of an operation plus its parameters (including its return type, if any) is called the operation's signature.
Signals are discussed in Chapter 21 . |
Note
The UML distinguishes between operation and method. An operation specifies a service that can be requested from any object of the class to affect behavior; a method is an implementation of an operation. Every nonabstract operation of a class must have a method, which supplies an executable algorithm as a body (generally designated in some programming language or structured text). In an inheritance lattice, there may be many methods for the same operation, and polymorphism selects which method in the hierarchy is dispatched during run time.
In its full form, the syntax of an operation in the UML is
You can also use stereotypes to designate sets of related operations, such as helper functions, as discussed in Chapter 6 . |
[visibility] name ['(' parameter-list ')']
[':' return-type]
[property-string {',' property-string}]
For example, the following are all legal operation declarations:
Name only | |
Visibility and name | |
Name and parameters | |
Name and return type | |
Name and property |
In an operation's signature, you may provide zero or more parameters, each of which follows the syntax
[direction] name : type [= default-value]
Direction may be any of the following values:
Note
An out or inout parameter is equivalent to a return parameter and an in parameter. Out and inout are provided for compatibility with older programming languages. Use explicit return parameters instead.
In addition to the leaf and abstract properties described earlier, there are defined properties that you can use with operations.
The concurrency properties (sequential, guarded, concurrent) address the concurrency semantics of an operation, properties that are relevant only in the presence of active objects, processes, or threads.
Active objects, processes, and threads are discussed in Chapter 23 . |
Template Classes
A template is a parameterized element. In such languages as C++ and Ada, you can write template classes, each of which defines a family of classes. (You can also write template functions, each of which defines a family of functions.) A template may include slots for classes, objects, and values, and these slots serve as the template's parameters. You can't use a template directly; you have to instantiate it first. Instantiation involves binding these formal template parameters to actual ones. For a template class, the result is a concrete class that can be used just like any ordinary class.
The basic properties of classes are discussed in Chapter 4 . |
The most common use of template classes is to specify containers that can be instantiated for specific elements, making them type-safe. For example, the following C++ code fragment declares a parameterized Map class.
template<class Item, class VType, int Buckets>
class Map {
public:
virtual map(const Item&, const VType&);
virtual Boolean isMappen(const Item&) const;
...
};
You might then instantiate this template to map Customer objects to Order objects.
m : Map<Customer, Order, 3>;
You can model template classes in the UML as well. As Figure 9-7 shows, you render a template class just as you do an ordinary class, but with an additional dashed box in the upper-right corner of the class icon, which lists the template parameters.
Figure 9-7. Template Classes

Dependencies are discussed in Chapters 5 and 10; stereotypes are discussed in Chapter 6 . |
As the figure goes on to show, you can model the instantiation of a template class in two ways. First, you can do so implicitly, by declaring a class whose name provides the binding. Second, you can do so explicitly, by using a dependency stereotyped as bind, which specifies that the source instantiates the target template using the actual parameters.
Standard Elements
All of the UML's extensibility mechanisms apply to classes. Most often, you'll use tagged values to extend class properties (such as specifying the version of a class) and stereotypes to specify new kinds of components (such as model- specific components).
The UML's extensibility mechanisms are discussed in Chapter 6 . |
The UML defines four standard stereotypes that apply to classes.
1. metaclass