Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

AhmadLang / Java, How To Program, 2004

.pdf
Скачиваний:
630
Добавлен:
31.05.2015
Размер:
51.82 Mб
Скачать

[Page 257 (continued)]

6.12. Method Overloading

Methods of the same name can be declared in the same class, as long as they have different sets of parameters (determined by the number, types and order of the parameters)this is called method overloading. When an overloaded method is called, the Java compiler selects the appropriate method by examining the number, types and order of the arguments in the call. Method overloading is commonly used to create several methods with the same name that perform the same or similar tasks, but on different types or different numbers of arguments. For example, Math methods abs, min and max (summarized in Section 6.3) are overloaded with four versions each:

[Page 258]

1.One with two double parameters.

2.One with two float parameters.

3.One with two int parameters.

4.One with two long parameters.

Our next example demonstrates declaring and invoking overloaded methods. You will see examples of overloaded constructors in Chapter 8.

Declaring Overloaded Methods

In our class MethodOverload (Fig. 6.13), we include two overloaded versions of a method called squareone that calculates the square of an int (and returns an int) and one that calculates the square

of a double (and returns a double). Although these methods have the same name and similar parameter lists and bodies, you can think of them simply as different methods. It may help to think of the method names as "square of int" and "square of double," respectively. When the application begins execution, class MethodOverloadTest's main method (Fig. 6.14, lines 610) creates an object of class MethodOverload (line 8) and calls the object's method testOverloadedMethods (line 9) to produce the program's output (Fig. 6.14).

Figure 6.13. Overloaded method declarations.

(This item is displayed on pages 258 - 259 in the print version)

1// Fig. 6.13: MethodOverload.java

2// Overloaded method declarations.

4public class MethodOverload

5{

6// test overloaded square methods

7public void testOverloadedMethods()

8{

9System.out.printf( "Square of integer 7 is %d\n", square( 7 ) );

10

System.out.printf( "Square of double 7.5 is %f\n", square( 7.5 ) );

11

} // end method testOverloadedMethods

12

 

13// square method with int argument

14public int square( int intValue )

15{

16System.out.printf( "\nCalled square with int argument: %d\n",

17intValue );

18return intValue * intValue;

19} // end method square with int argument

20

21// square method with double argument

22public double square( double doubleValue )

23{

24System.out.printf( "\nCalled square with double argument: %f\n",

25doubleValue );

26return doubleValue * doubleValue;

27} // end method square with double argument

28} // end class MethodOverload

Figure 6.14. Overloaded method declarations.

(This item is displayed on page 259 in the print version)

1// Fig. 6.14: MethodOverloadTest.java

2// Application to test class MethodOverload.

4public class MethodOverloadTest

5{

6public static void main( String args[] )

7{

8MethodOverload methodOverload = new MethodOverload();

9methodOverload.testOverloadedMethods();

10} // end main

11} // end class MethodOverloadTest

Called square with int argument: 7

Square of integer 7 is 49

Called square with double argument: 7.500000

Square of double 7.5 is 56.250000

[Page 259]

In Fig. 6.13, line 9 invokes method square with the argument 7. Literal integer values are treated as type int, so the method call on line 9 invokes the version of square at lines 1419 that specifies an int parameter. Similarly, line 10 invokes method square with the argument 7.5. Literal floating-point values are treated as type double, so the method call on line 10 invokes the version of square at lines 2227 that specifies a double parameter. Each method first outputs a line of text to prove that the proper method was called in each case. In line 10, note that the argument value and return value are displayed with the format specifier %f and that we did not specify a precision in either case. By default, floatingpoint values are displayed with six digits of precision if the precision is not specified in the format specifier.

Distinguishing Between Overloaded Methods

The compiler distinguishes overloaded methods by their signaturea combination of the method's name and the number, types and order of its parameters. If the compiler looked only at method names during compilation, the code in Fig. 6.13 would be ambiguousthe compiler would not know how to distinguish between the two square methods (lines 1419 and 2227). Internally, the compiler uses longer method names that include the original method name, the types of each parameter and the exact order of the parameters to determine whether the methods in a class are unique in that class.

[Page 260]

For example, in Fig. 6.13, the compiler might use the logical name "square of int" for the square method that specifies an int parameter and "square of double" for the square method that specifies a

double parameter (the actual names the compiler uses are messier). If method1's declaration begins as

void method1( int a, float b )

then the compiler might use the logical name "method1 of int and float." If the parameters are specified as

void method1( float a, int b )

then the compiler might use the logical name "method1 of float and int." Note that the order of the parameter types is importantthe compiler considers the preceding two method1 headers to be distinct.

Return Types of Overloaded Methods

In discussing the logical names of methods used by the compiler, we did not mention the return types of the methods. This is because method calls cannot be distinguished by return type. The program in Fig. 6.15 illustrates the compiler errors generated when two methods have the same signature and different return types. Overloaded methods can have different return types if the methods have different parameter lists. Also, overloaded methods need not have the same number of parameters.

Figure 6.15. Overloaded method declarations with identical signatures cause compilation errors, even if the return types are different.

1// Fig. 6.15: MethodOverloadError.java

2// Overloaded methods with identical signatures

3

// cause compilation errors, even if return types are different.

4

 

5public class MethodOverloadError

6{

7

// declaration of method

square with int argument

8

public int square( int x

)

9{

10return x * x;

11}

12

13// second declaration of method square with int argument

14// causes compilation error even though return types are different

15public double square( int y )

16{

17return y * y;

18}

19} // end class MethodOverloadError

MethodOverloadError.java:15: square(int) is already defined in MethodOverloadError

public double square( int y )

^

1 error

[Page 261]

Common Programming Error 6.11

Declaring overloaded methods with identical parameter lists is a compilation error regardless of whether the return types are different.

[Page 261 (continued)]

6.13. (Optional) GUI and Graphics Case Study: Colors and Filled Shapes

Although you can create many interesting designs with just lines and basic shapes, class Graphics provides many more capabilities. The next two features we introduce are colors and filled shapes. Adding color brings another dimension to the drawings a user sees on the computer screen. Filled shapes fill entire regions with solid colors, rather than just drawing outlines.

Colors displayed on computer screens are defined by their red, green, and blue components. These components, called RGB values, have integer values from 0 to 255. The higher the value of a particular component, the brighter the particular shade will be in the final color. Java uses class Color in package java.awt to represent colors using their RGB values. For convenience, the Color object contains 13 predefined static Color objectsColor.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY,

Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE and Color.YELLOW. Class Color also contains a constructor of the form:

public Color( int r, int g, int b )

so you can create custom colors by specifying values for the individual red, green and blue components of a color.

Filled rectangles and filled ovals are drawn using Graphics methods fillRect and fillOval, respectively. These two methods have the same parameters as their unfilled counterparts drawRect and drawOval; the first two parameters are the coordinates for the upper-left corner of the shape, while the next two parameters determine its width and height. The example in Fig. 6.16 and Fig. 6.17 demonstrates colors and filled shapes by drawing and displaying a yellow smiley face on the screen.

Figure 6.16. Drawing a smiley face using colors and filled shapes.

(This item is displayed on page 262 in the print version)

1// Fig. 6.16: DrawSmiley.java

2// Demonstrates filled shapes.

3import java.awt.Color;

4import java.awt.Graphics;

5import javax.swing.JPanel;

6

7public class DrawSmiley extends JPanel

8{

9public void paintComponent( Graphics g )

10{

11super.paintComponent( g );

12

13// draw the face

14g.setColor( Color.YELLOW );

15g.fillOval( 10, 10, 200, 200 );

17// draw the eyes

18g.setColor( Color.BLACK );

19g.fillOval( 55, 65, 30, 30 );

20g.fillOval( 135, 65, 30, 30 );

22// draw the mouth

23g.fillOval( 50, 110, 120, 60 );

25// "touch up" the mouth into a smile

26g.setColor( Color.YELLOW );

27g.fillRect( 50, 110, 120, 30 );

28g.fillOval( 50, 120, 120, 40 );

29} // end method paintComponent

30} // end class DrawSmiley

Figure 6.17. Creating JFrame to display a smiley face.

 

 

(This item is displayed on pages 262 - 263 in the print version)

1

//

Fig. 6.17: DrawSmileyTest.java

2

//

Test application that displays a smiley face.

3

import javax.swing.JFrame;

4

 

 

5public class DrawSmileyTest

6{

7public static void main( String args[] )

8{

9DrawSmiley panel = new DrawSmiley();

10JFrame application = new JFrame();

12application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

13application.add( panel );

14application.setSize( 230, 250 );

15application.setVisible( true );

16} // end main

17} // end class DrawSmileyTest

The import statements in lines 35 of Fig. 6.16 import Color, Graphics and JPanel. Class DrawSmiley uses class Color to specify drawing colors and class Graphics to draw. Class JPanel again provides the area in which we draw. Line 14 in method paintComponent uses Graphics method setColor to set the current drawing color to Color.YELLOW. Method setColor requires one argument, the Color to set as the drawing color. In this case, we use the predefined object Color.YELLOW. Line 15 draws a circle with diameter 200 to represent the facewhen the width and height arguments are identical, method fillOval draws a circle. Next, line 18 sets the color to Color.Black, and lines 1920 draw the eyes. Line 23 draws the mouth as an oval, but this is not quite what we want. To create a happy face, we will "touch up" the mouth. Line 26 sets the color to Color.YELLOW, so any shapes we draw will blend in with the face. Line 27 draws a rectangle that is half the mouth's height. This "erases" the top half of the mouth, leaving just the bottom half. To create a better smile, line 28 draws another oval to slightly cover the upper portion of the mouth. Class DrawSmileyTest (Fig. 6.17) creates and displays a JFrame containing the drawing, resulting in the system calling method paintComponent to draw the smiley face.

[Page 263]

GUI and Graphics Case Study Exercises

6.1Using method fillOval, draw a bull's-eye that alternates between two random colors, as in Fig. 6.18. Use the constructor Color( int r, int g, int b ) with random arguments to generate random colors.

Figure 6.18. A bull's-eye with two alternating, random colors.

6.2Create a program that draws 10 random filled shapes in random colors and positions (Fig. 6.19). Method paintComponent should contain a loop that iterates 10 times. In each iteration, the loop should determine whether to draw a filled rectangle or an oval, create a random color and choose coordinates and dimensions at random. The coordinates should be chosen based on the panel's width and height. Lengths of sides should be limited to half the width or height of the window. What happens each time paintComponent is called (i.e., the window is resized, uncovered, etc.)? We will resolve this issue in Chapter 8.

Figure 6.19. Randomly generated shapes.

(This item is displayed on page 264 in the print version)

[Page 263 (continued)]

6.14. (Optional) Software Engineering Case Study: Identifying

Class Operations

In the "Software Engineering Case Study" sections at the ends of Chapters 3, 4 and 5, we performed the first few steps in the object-oriented design of our ATM system. In Chapter 3, we identified the classes that we will need to implement and created our first class diagram. In Chapter 4, we described some attributes of our classes. In Chapter 5, we examined objects' states and modeled objects' state transitions and activities. In this section, we determine some of the class operations (or behaviors) needed to implement the ATM system.

[Page 264]

Identifying Operations

An operation is a service that objects of a class provide to clients (users) of the class. Consider the operations of some real-world objects. A radio's operations include setting its station and volume (typically invoked by a person adjusting the radio's controls). A car's operations include accelerating (invoked by the driver pressing the accelerator pedal), decelerating (invoked by the driver pressing the brake pedal or releasing the gas pedal), turning and shifting gears. Software objects can offer operations as wellfor example, a software graphics object might offer operations for drawing a circle, drawing a line, drawing a square and the like. A spreadsheet software object might offer operations like printing the spreadsheet, totaling the elements in a row or column and graphing information in the spreadsheet as a bar chart or pie chart.

We can derive many of the operations of each class by examining the key verbs and verb phrases in the requirements document. We then relate each of these to particular classes in our system (Fig. 6.20). The verb phrases in Fig. 6.20 help us determine the operations of each class.

Figure 6.20. Verbs and verb phrases for each class in the ATM system.

(This item is displayed on page 265 in the print version)

Class

Verbs and verb phrases

 

 

ATM

executes financial transactions

BalanceInquiry

[none in the requirements document]

Withdrawal

[none in the requirements document]

Deposit

[none in the requirements document]

BankDatabase

authenticates a user, retrieves an account balance, credits a deposit

 

amount to an account, debits a withdrawal amount from an account

Account

retrieves an account balance, credits a deposit amount to an account,

 

debits a withdrawal amount from an account

Screen

displays a message to the user

Keypad

receives numeric input from the user

CashDispenser

dispenses cash, indicates whether it contains enough cash to satisfy a

 

withdrawal request

DepositSlot

receives a deposit envelope

 

 

Modeling Operations

To identify operations, we examine the verb phrases listed for each class in Fig. 6.20. The "executes financial transactions" phrase associated with class ATM implies that class ATM instructs transactions to execute. Therefore, classes BalanceInquiry, Withdrawal and Deposit each need an operation to provide this service to the ATM. We place this operation (which we have named execute) in the third compartment of the three transaction classes in the updated class diagram of Fig. 6.21. During an ATM session, the ATM object will invoke the execute operation of each transaction object to tell it to execute.

Figure 6.21. Classes in the ATM system with attributes and operations.

(This item is displayed on page 266 in the print version)

[View full size image]

[Page 265]

The UML represents operations (which are implemented as methods in Java) by listing the operation name, followed by a comma-separated list of parameters in parentheses, a colon and the return type:

operationName ( parameter1, parameter2, ..., parameterN ) : return type

Each parameter in the comma-separated parameter list consists of a parameter name, followed by a colon and the parameter type:

parameterName : parameterType

For the moment, we do not list the parameters of our operationswe will identify and model the parameters of some of the operations shortly. For some of the operations, we do not yet know the return types, so we also omit them from the diagram. These omissions are perfectly normal at this point. As our design and implementation proceed, we will add the remaining return types.

Figure 6.20 lists the phrase "authenticates a user" next to class BankDatabasethe database is the object that contains the account information necessary to determine whether the account number and PIN entered by a user match those of an account held at the bank. Therefore, class BankDatabase needs an operation that provides an authentication service to the ATM. We place the operation authenticateUser in the third compartment of class BankDatabase (Fig. 6.21). However, an object of class Account, not class BankDatabase, stores the account number and PIN that must be accessed to authenticate a user, so class Account must provide a service to validate a PIN obtained through user input against a PIN stored in an Account object. Therefore, we add a validatePIN operation to class

Account. Note that we specify a return type of Boolean for the authenticateUser and validatePIN operations. Each operation returns a value indicating either that the operation was successful in performing its task (i.e., a return value of true) or that it was not (i.e., a return value of false).

[Page 266]

Figure 6.20 lists several additional verb phrases for class BankDatabase: "retrieves an account balance," "credits a deposit amount to an account" and "debits a withdrawal amount from an account." Like "authenticates a user," these remaining phrases refer to services that the database must provide to the ATM, because the database holds all the account data used to authenticate a user and perform ATM transactions. However, objects of class Account actually perform the operations to which these phrases refer. Thus, we assign an operation to both class BankDatabase and class Account to correspond to each of these phrases. Recall from Section 3.10 that, because a bank account contains sensitive information, we do not allow the ATM to access accounts directly. The database acts as an intermediary between the ATM and the account data, thus preventing unauthorized access. As we will see in Section 7.14, class ATM invokes the operations of class BankDatabase, each of which in turn invokes the operation with the same name in class Account.

[Page 267]

The phrase "retrieves an account balance" suggests that classes BankDatabase and Account each need a getBalance operation. However, recall that we created two attributes in class Account to represent a balanceavailableBalance and totalBalance. A balance inquiry requires access to both balance attributes so that it can display them to the user, but a withdrawal needs to check only the value of availableBalance. To allow objects in the system to obtain each balance attribute individually, we add operations getAvailableBalance and getTotalBalance to the third compartment of classes BankDatabase and Account (Fig. 6.21). We specify a return type of Double for these operations because the balance attributes which they retrieve are of type Double.

The phrases "credits a deposit amount to an account" and "debits a withdrawal amount from an account" indicate that classes BankDatabase and Account must perform operations to update an account during a deposit and withdrawal, respectively. We therefore assign credit and debit operations to classes BankDatabase and Account. You may recall that crediting an account (as in a deposit) adds an amount only to the totalBalance attribute. Debiting an account (as in a withdrawal), on the other hand, subtracts the amount from both balance attributes. We hide these implementation details inside class Account. This is a good example of encapsulation and information hiding.

If this were a real ATM system, classes BankDatabase and Account would also provide a set of operations to allow another banking system to update a user's account balance after either confirming or rejecting all or part of a deposit. Operation confirmDepositAmount, for example, would add an amount to the availableBalance attribute, thus making deposited funds available for withdrawal. Operation rejectDepositAmount would subtract an amount from the totalBalance attribute to indicate that a specified amount, which had recently been deposited through the ATM and added to the totalBalance, was not found in the deposit envelope. The bank would invoke this operation after determining either that the user failed to include the correct amount of cash or that any checks did not clear (i.e, they "bounced"). While adding these operations would make our system more complete, we do not include them in our class diagrams or our implementation because they are beyond the scope of the case study.

Class Screen "displays a message to the user" at various times in an ATM session. All visual output occurs through the screen of the ATM. The requirements document describes many types of messages