Class relationships
Beyond inheritance and interface implementation, UML gives you four flavors of "this object knows about that one", and the difference between them is entirely about lifetime - how long the link lasts and who controls it.
Association
One object uses another, usually held as a field for the lifetime of both. A professor communicates with students. Bidirectional associations are perfectly normal, and then the arrow has a point at each end.
Dependency
A weaker version of association, with no permanent link between the objects. A class takes another as a parameter or instantiates one locally. The test: if changing that class forces you to change this one, there is a dependency.
Composition
Whole and part, where the part cannot exist without the whole. A university consists of departments. Delete the university and the departments are not going anywhere on their own.
Aggregation
Composition with the leash off. A department contains professors, but professors survive the department and can belong to several at once.
The filled diamond means "I own your lifecycle", the hollow one means "I merely hold your number".
Realization
The last of the five, and the odd one out: Association, Dependency, Composition and
Aggregation all connect two concrete classes. Realization connects a class to an
interface - it is the "implements" arrow, drawn as a dashed line with a hollow
triangle. A Circle realizes Shape by promising to provide every method Shape
declares; the interface says what must exist, the class decides how.
You have actually been looking at this arrowhead already - every "implements" edge
drawn earlier in this section (an Airport accepting anything that is a
FlyingTransport, say) is a realization. This is just the first place this page
stops to name it. It is worth keeping separate from Dependency: a dependency is a
casual, droppable use of another class, while a realization is a binding contract -
drop a method the interface requires and the class simply does not compile. It is
also worth keeping separate from Extends: inheritance shares state and code down a
solid line because the subclass literally is a specialization of its parent, while
realization's dashed line shares nothing but an obligation - the implementing class
writes every line of its own method body.
Picking the right one
Ask two questions, in order. First: does the "part" object make sense without the
"whole"? If a Department is meaningless once its University is gone, that is
composition; if a Professor clearly outlives any one Department, that is aggregation.
Second, if the objects barely know about each other and the link is momentary rather
than a held field, stop - that is dependency, not association. Getting this wrong does not
crash a program, but it does mislead the next reader about what deleting an object
actually does to the objects it touches.
Before the quiz, try naming a few of these from scratch:
A Car has an Engine, and the engine cannot exist without the car.
Check yourself
A Professor object holds a reference to a Salary object only for the duration of one payroll() call, then discards it. What relationship is that?