A class can have references to objects of other classes as members. Such a capability is called composition and is sometimes referred to as a has-a relationship. For example, an object of class AlarmClock needs to know the current time and the time when it is supposed to sound its alarm, so it is reasonable to include two references to Time objects as members of the AlarmClock object.
Software Engineering Observation 8.9
One form of software reuse is composition, in which a class has as members references to objects of other classes. |
Our example of composition contains three classesDate (Fig. 8.7), Employee (Fig. 8.8) and EmployeeTest (Fig. 8.9). Class Date (Fig. 8.7) declares instance variables month, day and year (lines 68) to represent a date. The constructor receives three int parameters. Line 14 invokes utility method checkMonth (lines 2333) to validate the monthan out-of-range value is set to 1 to maintain a consistent state. Line 15 assumes that the value for year is correct and does not validate it. Line 16 invokes utility method checkDay (lines 3652) to validate the value for day based on the current month and year. Lines 4243 determine whether the day is correct based on the number of days in the particular month. If the day is not correct, lines 4647 determine whether the month is February, the day is 29 and the year is a leap year. If lines 4248 do not return a correct value for day, line 51 returns 1 to maintain the Date in a consistent state. Note that lines 1819 in the constructor output the this reference as a String. Since this is a reference to the current Date object, the object's toString method (lines 5558) is called implicitly to obtain the object's String representation.
Figure 8.7. Date class declaration.
(This item is displayed on pages 374 - 375 in the print version)
1 // Fig. 8.7: Date.java 2 // Date class declaration. 3 4 public class Date 5 { 6 private int month; // 1-12 7 private int day; // 1-31 based on month 8 private int year; // any year 9 10 // constructor: call checkMonth to confirm proper value for month; 11 // call checkDay to confirm proper value for day 12 public Date( int theMonth, int theDay, int theYear ) 13 { 14 month = checkMonth( theMonth ); // validate month 15 year = theYear; // could validate year 16 day = checkDay( theDay ); // validate day 17 18 System.out.printf( 19 "Date object constructor for date %s ", this ); 20 } // end Date constructor 21 22 // utility method to confirm proper month value 23 private int checkMonth( int testMonth ) 24 { 25 if ( testMonth > 0 && testMonth <= 12 ) // validate month 26 return testMonth; 27 else // month is invalid 28 { 29 System.out.printf( 30 "Invalid month (%d) set to 1.", testMonth ); 31 return 1; // maintain object in consistent state 32 } // end else 33 } // end method checkMonth 34 35 // utility method to confirm proper day value based on month and year 36 private int checkDay( int testDay ) 37 { 38 int daysPerMonth[] = 39 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 40 41 // check if day in range for month 42 if ( testDay > 0 && testDay <= daysPerMonth[ month ] ) 43 return testDay; 44 45 // check for leap year 46 if ( month == 2 && testDay == 29 && ( year % 400 == 0 || 47 ( year % 4 == 0 && year % 100 != 0 ) ) ) 48 return testDay; 49 50 System.out.printf( "Invalid day (%d) set to 1.", testDay ); 51 return 1; // maintain object in consistent state 52 } // end method checkDay 53 54 // return a String of the form month/day/year 55 public String toString() 56 { 57 return String.format( "%d/%d/%d", month, day, year ); 58 } // end method toString 59 } // end class Date |
Figure 8.8. Employee class with references to other objects.
(This item is displayed on pages 375 - 376 in the print version)
1 // Fig. 8.8: Employee.java 2 // Employee class with references to other objects. 3 4 public class Employee 5 { 6 private String firstName; 7 private String lastName; 8 private Date birthDate; 9 private Date hireDate; 10 11 // constructor to initialize name, birth date and hire date 12 public Employee( String first, String last, Date dateOfBirth, 13 Date dateOfHire ) 14 { 15 firstName = first; 16 lastName = last; 17 birthDate = dateOfBirth; 18 hireDate = dateOfHire; 19 } // end Employee constructor 20 21 // convert Employee to String format 22 public String toString() 23 { 24 return String.format( "%s, %s Hired: %s Birthday: %s", 25 lastName, firstName, hireDate, birthDate ); 26 } // end method toString 27 } // end class Employee |
Figure 8.9. Composition demonstration.
(This item is displayed on page 376 in the print version)
1 // Fig. 8.9: EmployeeTest.java 2 // Composition demonstration. 3 4 public class EmployeeTest 5 { 6 public static void main( String args[] ) 7 { 8 Date birth = new Date( 7, 24, 1949 ); 9 Date hire = new Date( 3, 12, 1988 ); 10 Employee employee = new Employee( "Bob", "Blue", birth, hire ); 11 12 System.out.println( employee ); 13 } // end main 14 } // end class EmployeeTest
|
Class Employee (Fig. 8.8) has instance variables firstName, lastName, birthDate and hireDate. Members birthDate and hireDate (lines 89) are references to Date objects. This demonstrates that a class can have as instance variables references to objects of other classes. The Employee constructor (lines 1219) takes four parametersfirst, last, dateOfBirth and dateOfHire. The objects referenced by the parameters dateOfBirth and dateOfHire are assigned to the Employee object's birthDate and hireDate instance variables, respectively. Note that when class Employee's toString method is called, it returns a String containing the String representations of the two Date objects. Each of these Strings is obtained with an implicit call to the Date class's toString method.
Class EmployeeTest (Fig. 8.9) creates two Date objects (lines 89) to represent an Employee's birthday and hire date, respectively. Line 10 creates an Employee and initializes its instance variables by passing to the constructor two Strings (representing the Employee's first and last names) and two Date objects (representing the birthday and hire date). Line 12 implicitly invokes the Employee's toString method to display the values of its instance variables and demonstrate that the object was initialized properly.
Introduction to Computers, the Internet and the World Wide Web
Introduction to Java Applications
Introduction to Classes and Objects
Control Statements: Part I
Control Statements: Part 2
Methods: A Deeper Look
Arrays
Classes and Objects: A Deeper Look
Object-Oriented Programming: Inheritance
Object-Oriented Programming: Polymorphism
GUI Components: Part 1
Graphics and Java 2D™
Exception Handling
Files and Streams
Recursion
Searching and Sorting
Data Structures
Generics
Collections
Introduction to Java Applets
Multimedia: Applets and Applications
GUI Components: Part 2
Multithreading
Networking
Accessing Databases with JDBC
Servlets
JavaServer Pages (JSP)
Formatted Output
Strings, Characters and Regular Expressions
Appendix A. Operator Precedence Chart
Appendix B. ASCII Character Set
Appendix C. Keywords and Reserved Words
Appendix D. Primitive Types
Appendix E. (On CD) Number Systems
Appendix F. (On CD) Unicode®
Appendix G. Using the Java API Documentation
Appendix H. (On CD) Creating Documentation with javadoc
Appendix I. (On CD) Bit Manipulation
Appendix J. (On CD) ATM Case Study Code
Appendix K. (On CD) Labeled break and continue Statements
Appendix L. (On CD) UML 2: Additional Diagram Types
Appendix M. (On CD) Design Patterns
Appendix N. Using the Debugger
Inside Back Cover