Time Class Case Study: Overloaded Constructors

Time Class Case Study Overloaded Constructors

As you know, you can declare your own constructor to specify how objects of a class should be initialized. Next, we demonstrate a class with several overloaded constructors that enable objects of that class to be initialized in different ways. To overload constructors, simply provide multiple constructor declarations with different signatures. Recall from Section 6.12 that the compiler differentiates signatures by the number and types of the parameters in each signature.

Class Time2 with Overloaded Constructors

The default constructor for class Time1 (Fig. 8.1) initialized hour, minute and second to their default 0 values (which is midnight in universal time). The default constructor does not enable the class's clients to initialize the time with specific non-zero values. Class Time2 (Fig. 8.5) contains five overloaded constructors that provide convenient ways to initialize objects of the new class Time2. Every object each constructor initializes begins in a consistent state. In this program, four of the constructors invoke a fifth constructor, which, in turn, calls method setTime to ensure that the value supplied for hour is in the range 0 to 23 and that the values for minute and second are each in the range 0 to 59. If a value is out of range, it is set to zero by setTime (once again ensuring that each instance variable remains in a consistent state). The compiler invokes the appropriate constructor by matching the number and types of the arguments specified in the constructor call with the number and types of the parameters specified in each constructor declaration. Note that class Time2 also provides set and get methods for each instance variable.

Figure 8.5. Time2 class with overloaded constructors.

(This item is displayed on pages 366 - 368 in the print version)

 1 // Fig. 8.5: Time2.java
 2 // Time2 class declaration with overloaded constructors.
 4 public class Time2
 5 {
 6 private int hour; // 0 - 23
 7 private int minute; // 0 - 59
 8 private int second; // 0 - 59
10 // Time2 no-argument constructor: initializes each instance variable
11 // to zero; ensures that Time2 objects start in a consistent state 
12 public Time2() 
13 { 
14  this( 0, 0, 0 ); // invoke Time2 constructor with three arguments
15 } // end Time2 no-argument constructor 
17 // Time2 constructor: hour supplied, minute and second defaulted to 0
18 public Time2( int h ) 
19 { 
20  this ( h, 0, 0 ); // invoke Time2 constructor with three arguments
21 } // end Time2 one-argument constructor 
23 // Time2 constructor: hour and minute supplied, second defaulted to 0
24 public Time2( int h, int m ) 
25 { 
26  this( h, m, 0 ); // invoke Time2 constructor with three arguments 
27 } // end Time2 two-argument constructor 
29 // Time2 constructor: hour, minute and second supplied 
30 public Time2( int h, int m, int s ) 
31 { 
32  setTime( h, m, s ); // invoke setTime to validate time
33 } // end Time2 three-argument constructor 
35 // Time2 constructor: another Time2 object supplied 
36 public Time2( Time2 time ) 
37 { 
38  // invoke Time2 three-argument constructor 
39  this( time.getHour(), time.getMinute(), time.getSecond() );
40 } // end Time2 constructor with a Time2 object argument 
42 // Set Methods
43 // set a new time value using universal time; ensure that
44 // the data remains consistent by setting invalid values to zero
45 public void setTime( int h, int m, int s )
46 {
47 setHour( h ); // set the hour
48 setMinute( m ); // set the minute
49 setSecond( s ); // set the second
50 } // end method setTime
52 // validate and set hour
53 public void setHour( int h )
54 {
55 hour = ( ( h >= 0 && h < 24 ) ? h : 0 );
56 } // end method setHour
58 // validate and set minute
59 public void setMinute( int m )
60 {
61 minute = ( ( m >= 0 && m < 60 ) ? m : 0 );
62 } // end method setMinute
64 // validate and set second
65 public void setSecond( int s )
66 {
67 second = ( ( s >= 0 && s < 60 ) ? s : 0 );
68 } // end method setSecond
70 // Get Methods
71 // get hour value
72 public int getHour()
73 {
74 return hour;
75 } // end method getHour
77 // get minute value
78 public int getMinute()
79 {
80 return minute;
81 } // end method getMinute
83 // get second value
84 public int getSecond()
85 {
86 return second;
87 } // end method getSecond
89 // convert to String in universal-time format (HH:MM:SS)
90 public String toUniversalString()
91 {
92 return String.format(
93 "%02d:%02d:%02d", getHour(), getMinute(), getSecond() );
94 } // end method toUniversalString
96 // convert to String in standard-time format (H:MM:SS AM or PM)
97 public String toString()
98 {
99 return String.format( "%d:%02d:%02d %s",
100 ( (getHour() == 0 || getHour() == 12) ? 12 : getHour() % 12 ),
101 getMinute(), getSecond(), ( getHour() < 12 ? "AM" : "PM" ) );
102 } // end method toString
103 } // end class Time2

Class Time2's Constructors

Lines 1215 declare a so-called no-argument constructorthat is, a constructor invoked without arguments. Such a constructor simply initializes the object as specified in the constructor's body. In the body, we introduce a use of the this reference that is allowed only as the first statement in a constructor's body. Line 14 uses this in method-call syntax to invoke the Time2 constructor that takes three arguments (lines 3033). The no-argument constructor passes values of 0 for the hour, minute and second to the constructor with three parameters. Using the this reference as shown here is a popular way to reuse initialization code provided by another of the class's constructors rather than defining similar code in the no-argument constructor's body. We use this syntax in four of the five Time2 constructors to make the class easier to maintain and modify. If we need to change how objects of class Time2 are initialized, only the constructor that the class's other constructors call would need to be modified. In fact, even that constructor might not need modification in this example. That constructor simply calls the setTime method to perform the actual initialization, so it is possible that the changes the class might require would be localized to the set methods.

Common Programming Error 8.3

It is a syntax error when this is used in a constructor's body to call another constructor of the same class if that call is not the first statement in the constructor. It is also a syntax error when a method attempts to invoke a constructor directly via this.

Lines 1821 declare a Time2 constructor with a single int parameter representing the hour, which is passed with 0 for the minute and second to the constructor at lines 3033. Lines 2427 declare a Time2 constructor that receives two int parameters representing the hour and minute, which are passed with 0 for the second to the constructor at lines 3033. Like the no-argument constructor, each of these constructors invokes the constructor at lines 3033 to minimize code duplication. Lines 3033 declare the Time2 constructor that receives three int parameters representing the hour, minute and second. This constructor calls setTime to initialize the instance variables to consistent values.

Common Programming Error 8.4

A constructor can call methods of the class. Be aware that the instance variables might not yet be in a consistent state, because the constructor is in the process of initializing the object. Using instance variables before they have been initialized properly is a logic error.

Lines 3640 declare a Time2 constructor that receives a Time2 reference to another Time2 object. In this case, the values from the Time2 argument are passed to the three-argument constructor at lines 3033 to initialize the hour, minute and second. Note that line 39 could have directly accessed the hour, minute and second values of the constructor's argument time with the expressions time.hour, time.minute and time.secondeven though hour, minute and second are declared as private variables of class Time2. This is due to a special relationship between objects of the same class.

Software Engineering Observation 8.4

When one object of a class has a reference to another object of the same class, the first object can access all the second object's data and methods (including those that are private).


Notes Regarding Class Time2's Set and Get Methods and Constructors

Note that Time2's set and get methods are called throughout the body of the class. In particular, method setTime calls methods setHour, setMinute and setSecond in lines 4749, and methods toUniversalString and toString call methods getHour, getMinute and getSecond in line 93 and lines 100101, respectively. In each case, these methods could have accessed the class's private data directly without calling the set and get methods. However, consider changing the representation of the time from three int values (requiring 12 bytes of memory) to a single int value representing the total number of seconds that have elapsed since midnight (requiring only 4 bytes of memory). If we make such a change, only the bodies of the methods that access the private data directly would need to changein particular, the individual set and get methods for the hour, minute and second. There would be no need to modify the bodies of methods setTime, toUniversalString or toString because they do not access the data directly. Designing the class in this manner reduces the likelihood of programming errors when altering the class's implementation.

Similarly, each Time2 constructor could be written to include a copy of the appropriate statements from method setTime. Doing so may be slightly more efficient, because the extra constructor call and call to setTime are eliminated. However, duplicating statements in multiple methods or constructors makes changing the class's internal data representation more difficult. Having the Time2 constructors call the constructor with three arguments (or even call setTime directly) requires any changes to the implementation of setTime to be made only once.

Software Engineering Observation 8.5

When implementing a method of a class, use the class's set and get methods to access the class's private data. This simplifies code maintenance and reduces the likelihood of errors.


Using Class Time2's Overloaded Constructors

Class Time2Test (Fig. 8.6) creates six Time2 objects (lines 813) to invoke the overloaded Time2 constructors. Line 8 shows that the no-argument constructor (lines 1215 of Fig. 8.5) is invoked by placing an empty set of parentheses after the class name when allocating a Time2 object with new. Lines 913 of the program demonstrate passing arguments to the other Time2 constructors. Java invokes the appropriate overloaded constructor by matching the number and types of the arguments specified in the constructor call with the number and types of the parameters specified in each constructor declaration. Line 9 invokes the constructor at lines 1821 of Fig. 8.5. Line 10 invokes the constructor at lines 2427 of Fig. 8.5. Lines 1112 invoke the constructor at lines 3033 of Fig. 8.5. Line 13 invokes the constructor at lines 3640 of Fig. 8.5. The application displays the String representation of each initialized Time2 object to confirm that it was initialized properly.

Figure 8.6. Overloaded constructors used to initialize Time2 objects.

(This item is displayed on pages 370 - 371 in the print version)

 1 // Fig. 8.6: Time2Test.java
 2 // Overloaded constructors used to initialize Time2 objects.
 4 public class Time2Test
 5 {
 6 public static void main( String args[] )
 7 {
 8 Time2 t1 = new Time2(); // 00:00:00
 9 Time2 t2 = new Time2( 2 ); // 02:00:00
10 Time2 t3 = new Time2( 21, 34 ); // 21:34:00
11 Time2 t4 = new Time2( 12, 25, 42 ); // 12:25:42
12 Time2 t5 = new Time2( 27, 74, 99 ); // 00:00:00
13 Time2 t6 = new Time2( t4 ); // 12:25:42
15 System.out.println( "Constructed with:" );
16 System.out.println( "t1: all arguments defaulted" );
17 System.out.printf( " %s
", t1.toUniversalString() );
18 System.out.printf( " %s
", t1.toString() );
20 System.out.println(
21 "t2: hour specified; minute and second defaulted" );
22 System.out.printf( " %s
", t2.toUniversalString() );
23 System.out.printf( " %s
", t2.toString() );
25 System.out.println(
26 "t3: hour and minute specified; second defaulted" );
27 System.out.printf( " %s
", t3.toUniversalString() );
28 System.out.printf( " %s
", t3.toString() );
30 System.out.println( "t4: hour, minute and second specified" );
31 System.out.printf( " %s
", t4.toUniversalString() );
32 System.out.printf( " %s
", t4.toString() );
34 System.out.println( "t5: all invalid values specified" );
35 System.out.printf( " %s
", t5.toUniversalString() );
36 System.out.printf( " %s
", t5.toString() );
38 System.out.println( "t6: Time2 object t4 specified" );
39 System.out.printf( " %s
", t6.toUniversalString() );
40 System.out.printf( " %s
", t6.toString() );
41 } // end main
42 } // end class Time2Test
t1: all arguments defaulted
 12:00:00 AM
t2: hour specified; minute and second defaulted
 2:00:00 AM
t3: hour and minute specified; second defaulted
 9:34:00 PM
t4: hour, minute and second specified
 12:25:42 PM
t5: all invalid values specified
 12:00:00 AM
t6: Time2 object t4 specified
 12:25:42 PM

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


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


Searching and Sorting

Data Structures



Introduction to Java Applets

Multimedia: Applets and Applications

GUI Components: Part 2



Accessing Databases with JDBC


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

Java(c) How to Program
Java How to Program (6th Edition) (How to Program (Deitel))
ISBN: 0131483986
EAN: 2147483647
Year: 2003
Pages: 615

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net