AhmadLang / Java, How To Program, 2004
.pdf
After instantiation: number: 0; string: Hello
After changing values: number: 77; string: Goodbye
In the PackageData class declaration, lines 2627 declare the instance variables number and string with no access modifierstherefore, these are package-access instance variables. The PackageDataTest application's main method creates an instance of the PackageData class (line 9) to demonstrate the ability to modify the PackageData instance variables directly (as shown on lines 1516). The results of the modification can be seen in the output window.
[Page 396 (continued)]
8.18. (Optional) GUI and Graphics Case Study: Using Objects with Graphics
Most of the graphics you have seen to this point did not vary each time you executed the program. However, Exercise 6.2 asked you to create a program that generated shapes and colors at random. In that exercise, the drawing changed every time the system called paintComponent to redraw the panel. To create a more consistent drawing that remains the same each time it is drawn, we must store information about the displayed shapes so that we can reproduce them exactly each time the system calls
paintComponent.
[Page 398]
To do this, we will create a set of shape classes that store information about each shape. We will make these classes "smart" by allowing objects of these classes to draw themselves if provided with a Graphics object. Figure 8.21 declares class MyLine, which has all these capabilities.
Figure 8.21. MyLine class represents a line.
1// Fig. 8.21: MyLine.java
2// Declaration of class MyLine.
3import java.awt.Color;
4import java.awt.Graphics;
5
6public class MyLine
7{
8 private int x1; // x coordinate of first endpoint
9private int y1; // y coordinate of first endpoint
10private int x2; // x coordinate of second endpoint
11private int y2; // y coordinate of second endpoint
12private Color myColor; // color of this shape
13
14 // constructor with input values
15 public MyLine( int x1, int y1, int x2, int y2, Color color )
16{
17this.x1 = x1; // set x coordinate of first endpoint
18this.y1 = y1; // set y coordinate of first endpoint
19this.x2 = x2; // set x coordinate of second endpoint
20this.y2 = y2; // set y coordinate of second endpoint
21myColor = color; // set the color
22} // end MyLine constructor
23
24// Draw the line in the specified color
25public void draw( Graphics g )
26{
27g.setColor( myColor );
28g.drawLine( x1, y1, x2, y2 );
29} // end method draw
30} // end class MyLine
Class MyLine imports Color and Graphics (lines 34). Lines 811 declare instance variables for the coordinates needed to draw a line, and line 12 declares the instance variable that stores the color of the line. The constructor at lines 1522 takes five parameters, one for each instance variable that it initializes. Method draw at lines 2529 requires a Graphics object and uses it to draw the line in the proper color and at the proper coordinates.
In Fig. 8.22, we declare class DrawPanel, which will generate random objects of class MyLine. Line 12 declares a MyLine array to store the lines to draw. Inside the constructor (lines 1537), line 17 sets the
Class DrawPanel, which extends JPanel and handles the creation of the shapes, should declare three arrays, one for each shape type. The length of each array should be a random number between 1 and 5. The constructor of class DrawPanel will fill each of the arrays with shapes of random position, size, color and fill.
In addition, modify all three shape classes to include the following:
a.A constructor with no arguments that sets all the coordinates of the shape to 0, the color of the shape to Color.BLACK, and the filled property to false
(MyRect and MyOval only).
b.Set methods for the instance variables in each class. The methods that set a coordinate value should verify that the argument is greater than or equal to zero before setting the coordinateif it is not, they should set the coordinate to zero. The constructor should call the set methods rather than initialize the local variables directly.
c.Get methods for the instance variables in each class. Method draw should reference the coordinates by the get methods rather than access them directly.
[Page 401 (continued)]
8.19. (Optional) Software Engineering Case Study: Starting to Program the Classes of the ATM System
In the "Software Engineering Case Study" sections in Chapters 17, we introduced the fundamentals of object orientation and developed an object-oriented design for our ATM system. Earlier in this chapter, we discussed many of the details of programming with Java classes. We now begin implementing our object-oriented design in Java. At the end of this section, we show how to convert class diagrams to Java code. In the final "Software Engineering Case Study" section (Section 10.9), we modify the code to incorporate the object-oriented concept of inheritance. We present the full Java code implementation in Appendix J.
Visibility
We now apply access modifiers to the members of our classes. In Chapter 3, we introduced access modifiers public and private. Access modifiers determine the visibility or accessibility of an object's attributes and methods to other objects. Before we can begin implementing our design, we must consider which attributes and methods of our classes should be public and which should be private.
In Chapter 3, we observed that attributes normally should be private and that methods invoked by clients of a given class should be public. Methods that are called only by other methods of the class as "utility methods," however, normally should be private. The UML employs visibility markers for modeling the visibility of attributes and operations. Public visibility is indicated by placing a plus sign (+) before an operation or an attribute, whereas a minus sign () indicates private visibility. Figure 8.24 shows our updated class diagram with visibility markers included. [Note: We do not include any operation parameters in Fig. 8.24this is perfectly normal. Adding visibility markers does not affect the parameters already modeled in the class diagrams of Fig. 6.22Fig. 6.25.]
Figure 8.24. Class diagram with visibility markers.
(This item is displayed on page 402 in the print version)
[View full size image]
[View full size image]
Like the class diagram of Fig. 3.24, the class diagram of Fig. 8.25 omits classes BalanceInquiry and Deposit to keep the diagram simple. The navigability of the associations in which these classes participate closely parallels the navigability of class Withdrawal. Recall from Section 3.10 that BalanceInquiry has an association with class Screen. We can navigate from class BalanceInquiry to class Screen along this association, but we cannot navigate from class Screen to class BalanceInquiry. Thus, if we were to model class BalanceInquiry in Fig. 8.25, we would place a navigability arrow at class Screen's end of this association. Also recall that class Deposit associates with classes Screen, Keypad and DepositSlot. We can navigate from class Deposit to each of these classes, but not vice versa. We therefore would place navigability arrows at the Screen, Keypad and DepositSlot ends of these associations. [Note: We model these additional classes and associations in our final class diagram in Section 10.9, after we have simplified the structure of our system by incorporating the object-oriented concept of inheritance.]
[Page 403]
Implementing the ATM System from Its UML Design
We are now ready to begin implementing the ATM system. We first convert the classes in the diagrams of Fig. 8.24 and Fig. 8.25 into Java code. The code will represent the "skeleton" of the system. In Chapter 10, we modify the code to incorporate the object-oriented concept of inheritance. In Appendix J, ATM Case Study Code, we present the complete working Java code for our model.
As an example, we develop the code from our design of class Withdrawal in Fig. 8.24. We use this figure to determine the attributes and operations of the class. We use the UML model in Fig. 8.25 to determine the associations among classes. We follow the following four guidelines for each class:
1.Use the name located in the first compartment to declare the class as a public class with an empty no-argument constructor. We include this constructor simply as a placeholder to remind us that most classes will indeed need constructors. In Appendix J, when we complete a working version of this class, we add any necessary arguments and code the body of the constructor as needed. For example, class Withdrawal yields the code in Fig. 8.26. [Note: If we find that the
class's instance variables require only default initialization, then we remove the empty noargument constructor because it is unnecessary.]
[Page 404]
Figure 8.26. Java code for class Withdrawal based on Fig. 8.24 and Fig. 8.25.
1 // Class Withdrawal represents an ATM withdrawal transaction
2public class Withdrawal
3{
4// no-argument constructor
5public Withdrawal()
6{
7} // end no-argument Withdrawal constructor
8} // end class Withdrawal
2.Use the attributes located in the second compartment to declare the instance variables. For example, the private attributes accountNumber and amount of class Withdrawal yield the code in Fig. 8.27. [Note: The constructor of the complete working version of this class will assign values to these attributes.]
Figure 8.27. Java code for class Withdrawal based on Fig. 8.24 and Fig. 8.25.
1 // Class Withdrawal represents an ATM withdrawal transaction
2public class Withdrawal
3{
4// attributes
5 |
private |
int accountNumber; // account to withdraw funds from |
6 |
private |
double amount; // amount to withdraw |
7 |
|
|
8// no-argument constructor
9public Withdrawal()
10{
11} // end no-argument Withdrawal constructor
12} // end class Withdrawal
3.Use the associations described in the class diagram to declare the references to other objects. For example, according to Fig. 8.25, Withdrawal can access one object of class Screen, one object of class Keypad, one object of class CashDispenser and one object of class BankDatabase. This yields the code in Fig. 8.28. [Note: The constructor of the complete working version of this class will initialize these instance variables with references to actual objects.]
Figure 8.28. Java code for class Withdrawal based on Fig. 8.24 and Fig. 8.25.
(This item is displayed on page 405 in the print version)
1 // Class Withdrawal represents an ATM withdrawal transaction
2public class Withdrawal
3{
4// attributes
5 |
private |
int accountNumber; // account to withdraw funds from |
6 |
private |
double amount; // amount to withdraw |
7 |
|
|
8// references to associated objects
9private Screen screen; // ATM's screen
