Class diagrams are a convenient way to graphically depict classes and their properties and methods.
A class box is broken down into 3 sections:
Here _name
is an attribute of the Snowboarder
class. Its type is String
, you may leave off the type information.
The code might look like the following:
public class Snowboarder { private String _name; }
Remember attributes are simple properties which simply describe the object.
The diagram above shows that a Snowboarder
has a
Head
. That is, that the Head
is a subpart of the Snowboarder
.
Further, as Head
is a part of the Snowboarder
(the
whole), there are certain implications for lifetimes. That is that the Head
exists as long as the Snowboarder
does. Additionally, the Snowboarder
is incomplete without a head. Therefore, a Snowboarder must have an instance
variable of type Head and it must call the Head constructor, see:
public class Snowboarder { private String _name; private Head _head; // Step 1) of coding the "has a" relation. public Snowboarder() { _head = new Head(); // Step 2) of coding the "has a" relation. } // end Snowboarder constructor } // end class Snowboarder
public class Head {
public Head() { // do something interesting } }
Notice the lack of any information about the Snowboarder class
in the Head class. That is because, the composition relationship is one-way
only! That is, the Head
is blissfully unaware of the Snowboarder
.
Our model is becoming more complete. Since Snowboarder
s
are accident-prone, they need to know a SkiPatroller
, so
that they can be rescued. Since associations are a type of property there must
be an instance variable, however, the SkiPatroller is not a subpart of a Snowboarder.
The SkiPatroller exists prior to the Snowboarder. Instead, we must send in SkiPatroller
object into the constructor of a Snowboarder, like so:
public class Snowboarder { private String _name; private Head _head; private SkiPatroller _patroller; // Step 1) of coding the "knows a" relation public Snowboarder(SkiPatroller sp) { _head = new Head(); _patroller = sp; // Step 2) of coding the "knows a" relation } // end of Snowboarder constructor } // end class Snowboarder public class SkiPatroller { public SkiPatroller() { } }
Once again notice the lack of information about the Snowboarder
in SkiPatroller
. This too is a one-way relation, starting to see
a pattern?
SkiPatroller
s use sleds to rescue people. You can
show that one class is dependent on another via the uses relationship. The dashed
line above indicates that SkiPatroller
uses a Sled
.
This means that Sled is not an instance variable in SkiPatroller. Rather, something
in its code requires the sled class, it could be a local variable, a
formal parameter or merely have an unnamed instance created. Here
is an example that uses a local variable.
public class SkiPatroller { public void rescue(Snowboarder sb) { Sled sled = new Sled(); // SkiPatroller uses a Sled sled.load(sb); this.skiToPatrolRoom(); // method definition not shown } } public class Sled { public void load(Snowboarder bdr) { // implementation not shown } }
Once again notice the relationship is one-way.
The overall theme is that a Snowboarder
is just waiting
to get hurt, or colloquilly, an AccidentWaitingToHappen
. This is
the inheritance relation. It is modelled using the keyword extends.
public class AccidentWaitingToHappen { public void getHurt() { // implementation not shown, otherwise we'd need a parental advisory :) } } public class Snowboarder extends AccidentWaitingToHappen { // the rest of the code is omitted, since it is irrelevant in this relation. } // end class SnowboarderNote, the
AccidentWaitingToHappen
has no information
about a Snowboarder
.
This page originally created by Phil Ventura. Maintained by Adrienne Decker (adrienne@cse.buffalo.edu)