|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 3
class Engine
{
// fields and methods that identify the structure of an Engine
}
class Vehicle
{
Engine engine;
Vehicle (Engine e)
{
engine = e;
}
}
The above example declares two classes: Engine and Vehicle. Vehicle declares an Engine field named engine and uses that field to reference an object that describes the vehicle's engine. Vehicle's Vehicle (Engine e) constructor initializes engine to reference an Engine object by assigning the contents of parameter e to that field. After the assignment, engine references the same object as e. Figure 1 conceptualizes a Vehicle composed of an Engine.

Figure 1. A Vehicle composed of an Engine
Now that you know something about the structure of the Vehicle and Engine classes, how do you create an Engine object and a Vehicle object that are composed of the Engine object? For an answer, check out the following example:
Engine e = new Engine (); Vehicle v = new Vehicle (e);
In the example above, the first line creates the Engine object and assigns its address to Engine object reference variable e. The second line, which creates the Vehicle object, passes the Engine object address (in e) to Vehicle's constructor. In turn, the constructor saves the contents of e in its private engine field. Now, the Vehicle object referenced by v is composed of the Engine object referenced by Vehicle's internal engine field. The relationship between the newly created Vehicle and Engine objects appears in Figure 2.

Figure 2. The relationship between a Vehicle object and its Engine object
Although the previous composition examples are insightful, you can see the benefits of composition more clearly in a larger
application. Check out Listing 2's TimeDemo source code:
Listing 2. TimeDemo.java
// TimeDemo.java
class Time
{
// Declare three int variables that can only be directly accessed by
// the methods of this class.
private int hour, minute, second;
// Declare a constructor for constructing Time objects. This
// constructor saves the values of its arguments to the
// aforementioned hour, minute, and second variables.
Time (int h, int m, int s)
{
hour = h;
minute = m;
second = s;
}
// Declare methods for returning the hour, minute, and second values.
int getHour () { return hour; }
int getMinute () { return minute; }
int getSecond () { return second; }
}
class Display
{
// Because no explicit constructor(s) has/have been specified, Display
// is given a default no-argument constructor. You cannot see this
// constructor at the source code level but it exists at the byte code
// level.
// Declare a method for setting the current display time. This method
// takes a single Time argument. The current implementation extracts
// the hour, minute, and second components from the Time object and
// prints them on the standard output device.
void setDisplayTime (Time t)
{
System.out.println (t.getHour () + ":" +
t.getMinute () + ":" +
t.getSecond ());
}
}
class TimePiece
{
// Declare a private Display object reference variable.
// After all, every timepiece has a display (either analog or digital).
private Display d;
// Declare a private Time object reference variable. The Time object
// referenced by this variable represents the time to be displayed. It
// will be displayed by calling the Display object's setDisplayTime()
// method.
private Time t;
// Declare a constructor for constructing TimePiece objects. This
// constructor creates a Display object for displaying the time, and
// saves the address of its Time object in the previous Time variable
// t.
TimePiece (Time t)
{
d = new Display ();
this.t = t;
// Note: The keyword this is used to identify field variable t.
// If we didn't say this.t, we would be referring to the t
// argument variable passed to the constructor. The
// resulting t = t; expression would only save the contents
// of the argument variable to the argument variable -- not
// to the same-named field variable. Hence, nothing useful
// would be accomplished.
}
// Declare a method for starting the timepiece. At present, all this
// does is call the Display object's setDisplayTime() method with field
// variable t (referencing a Time object) as its argument.
void start ()
{
d.setDisplayTime (t);
}
}
class TimeDemo
{
// Declare the starting method -- main(). This means that TimeDemo is
// the first class to be loaded by the JVM, and starts the
// TimeDemo application.
public static void main (String [] args)
{
// Create a Time object with arbitrary values. Pass this object
// to the TimePiece constructor, and call the resulting object's
// start() method to start the timepiece.
new TimePiece (new Time (10, 15, 0)).start ();
}
}
TimeDemo models a real-world timepiece composed of a display and a time in source code. Because TimeDemo's source code is heavily commented, I won't delve into its inner workings. However, notice that the TimePiece class shows a TimePiece to be composed of a Display and a Time. By making a timepiece a composition of both a display and a time, composition mimics the real-world approach to building
timepieces. Not only does composition speed development of the timepiece, it also facilitates future maintenance. For example,
because displays can be either analogue or digital, you only need modify Display to create either an analogue or a digital timepiece.