ICOM 4015 Advanced Programming Laboratory Chapter 4 Introduction to Object Oriented Programming University of Puerto Rico Electrical and Computer Engineering Department by Juan E. Sur´ıs 1 Introduction In this chapter we will discuss the process of designing a class. We begin by discussing what functionality we wish the class to provide, followed by the deciding what is the necessary information to provide such functionality. Lastly, we must provide constructors for the class. Open the project called Lab4 provided. All your work should be part of this project. 2 Class Car With can think of a car as a vehicle that has a tank of gas and an associated fuel efficiency. As the car travels, gas is used. We wish to create a class for a car that represents the sim- plified version of the car we just described. Exercise 1: Create a new class called Car. 2.1 Class functionality The first step in designing a class is to define the functionality we wish the class to provide. In the description of a car provided, we are only concerned with the amount of gas used by the car. For the car to use any gas it must have traveled. So far we can conceive of the following operations: • Drive the car. Consumes the amount of gas needed to travel the number of miles driven. We can also add the number of miles driven to the odometer1. • Add gas. To allow the car to be driven long distances, we must add gas to the gas tank. • Calculate range. The range is the maximum number of miles the car can drive, given the amount of gas in the car. Once we know the operations we wish to provide, we must think of what data type each will return as well as the number and type of arguments needed. Following is a declaration of the method we will define for each operation: • public boolean drive(double miles) - To drive the car we need to know how many miles to do so. The number of miles could a decimal, so we will use a double. This method returns a double indicating the number of miles the car was able to drive. The number returned could be smaller than the argument provided if the car did not have enough gas to drive that amount. • public addGas(double newGas) - To add gas to the tank, we need to know the amount of gas to add to the tank. The amount of gas (measured in gallons) can be a decimal, so we will use a double. This method returns a double indicating the amount of gas in the tank after adding the new gas. 1The odometer is the device that keeps track of how many miles the car has been driven. 1 • public double range() - To calculate the range, we need the amount of gas in the tank and the gas efficiency of the car. The class already has this information available, so we do not need any arguments. This method returns the maximum number of miles we can drive with the amount of gas in the tank. Exercise 2: Add these method declarations (not the body) to the class Car, as in Figure 1. The methods should also have the appropriate javadoc comments. Have eclipse generate comments for you. Figure 1: Methods for class Car 2.2 Information Now we need to define the information we need to store in the class so that we can provide the necessary functionality. We can conceive of the following information: • double gas - the amount of gas in the car. • double gasEfficiency - the number of miles that cen be driven per gallon of gas. • double odometer - the total number of miles driven. Exercise 3: Add these instance fields to the class Car 2, as in Figure 2 The instance fields should be declared private. The fields should also have the appropriate javadoc comments. Have eclipse generate comments for you. 2You should add the instance fields at the top, before the method declarations. This is not mandatory, but makes your code easier to follow. 2 Figure 2: Instance fields for class Car 2.3 Constructor The last step before we can implement the methods is to define the constructor(s). Before we decide which constructors to provide, we need to decide for which instance fields we can assign reasonable default values. For the Car class, we can assign the following default values: • gas = 0 - if not given an initial value for the amount of gas, we can assume 0. • odometer = 0 - we will always assume the car has never been driven when the object is created. It is important to note that if we do not initialize instance fields, Java will assign 0 to all numeric data types. Therefore, it is not mandatory that we assign the default values as they coincide with the ones Java has assigned. However, for clarity it is good practice to assign these values anyway. Now that we know which fields have default values, we can decide on the constructor(s). All constructor must take as argument all fields which we do not have default values for. For the Car class we will implement the following constructors: • public Car(double gasEfficiency) • public Car(double gasEfficiency, double gas) Notice we did not provide a constructor with no arguments. If you do not declare any constructors, Java will add such a constructor. In this case, we have declared constructors, so Java will not add a constructor for us. 2.4 Implementation Now we have declared all instance fields, methods and constructors. The remaining thing to do is implement the constructors and methods. 2.4.1 Constructors Let us begin with the constructors. Fortunately, eclipse provides us with a way to automat- ically create them. Do Source → Generate Constructors from Fields. Figure 3 shows the 3 window used to create constructors. Select the fields you wish to include in the constructor you are currently generating. I this case, we want to select gas and gasEfficiency. Make sure you select the checkbox to generate the comments. Leave the checkbox to omit the call to the default constructor selected3. Figure 3: Constructor generation When you have eclipse generate a constructor, any field that is not selected as an argu- ment for the constructor will not have a default value assigned by the constructor. We will modify these constructors to assign default values. Exercise 4: Add the constructor implementations to the class Car 4, as in Figure 3. The declarations should also have the appropriate javadoc comments. Have eclipse generate the constructors and comments for you. Modify the generated constructors to assign default values to the fields for which we are not given values as arguments, as in Figure 4. Notice that the constructor that takes one argument looks exactly them same as the other constructor with the exception that it assigns a default value for the field gas. Instead of creating two constructors that are virtually alike, we can just create the one with two 3We will discuss this later in the semester 4You should add them after the instance fields but before the method declarations. This is not mandatory, but makes your code easier to follow. 4 Figure 4: Constructors for class Car arguments and use it to create the constructor with only one argument, using the keyword this. The following line tells Java to call the constructor with the given arguments: this(10.0, 5.0) This line can only be used in a constructor and must be the first line. Exercise 5: Modify the implementation for the constructor with only one argument so that it calls the other constructor, as in Figure 5. Figure 5: Modified constructors for class Car Exercise 6: Implement the methods, as in Figure 65. To finish with the Car class we need to declare and implement get and set methods for the instance fields. Usually we will provide get methods for all instance fields. However, we do not always wish to allow the instance fields to be changed from the outside of the class. Let us examine all the instance fields and decide whether we wish to provide a get method.: • gas - YES. We do wish to know how much gas is in the car. 5The comments are hidden for convinience. 5 Figure 6: Method implementations for class Car • gasEfficiency - YES. We do wish to know what the gas efficiency of the car is. • odometer - YES. We do wish to know how many miles the cars has been driven. and a set method: • gas - NO. The amount of gas can only be changed by calling the addGas method. • gasEfficiency - NO. The car efficiency of the car should not change. • odometer - NO. The odometer should only change when the car is driven. Exercise 6: Implement the get methods by doing Source → Generate Getters and Setters. Figure 7 shows the window where we tell eclipse which methods to create. Exercise 7: Execute the JUnit test called CarTester. Fix any problems in your code until all tests pass. 3 FaceComponent In the previous chapter we created a component that drew a face on a frame. We are now going to create a class called Face that takes care of the drawing. The component class will create a Face object and have it draw itself. 3.1 Create a Face class The project provided includes a partial implementation of the class. The first thing we want to point out about the file provided is the declaration of the instance fields. They all are of the form: private double x = 5.0 6 Figure 7: Getters and Setters for class Car This means that the field x is of type double and it will be initialized to the value 5.0. This is another way to assign default values to instance fields, other than by the constructor(s). Exercise 8: Implement the get/set methods for the Face class by doing Source → Generate Getters and Setters. Add comments to all methods. Exercise 9: Have eclipse generate the following constructors: • Face(double x, double y) • Face(double x, double y, double headHeight, double headWidth) 3.2 Create FaceComponent class The Face class has a method called draw that takes a Graphics2D argument. This is the method that will actually draw the face on the frame. We will create a component as we did in the last chapter, except that the paintComponent method will now only consist of a call to the draw method. Exercise 10: Create the classes FaceViewer and FaceComponent as shown in Figure 8 and Figure 9. Execute FaceViewer several times, each time changing some of the instance 7 fields using the appropriate methods. Figure 8: FaceComponent class Figure 9: FaceViewer class 4 Independent Exercises Complete the following exercises: 1. Problem P3.3 Write a class SavingsAccount that is similar to the BankAccount class, except that it has an added instance field interest. Supply two constructors: • One that sets both the initial balance and the interest rate, • Another that sets the interest rate and the initial balance to 0.0 by calling the first constructor. Supply the following methods, as well as the necessary get methods: 8 • deposit - the method takes a double argument indicating the amount to deposit. It returns the balance after the deposit. • withdraw - the method takes a double argument indicating the amount to with- draw. It returns the balance after the withdrawl. • addInterest - adds interest to the account and returns the amount of interest added. The interest should be calculated as follows: balance× interest 12 Your class should pass the JUnit test provided. 2. Problem P3.6 Implement a class Student. For the purpose of this exercise, a student has a name and a total quiz score. Supply a constructor that sets the name of the student and the following methods: • getName - return the name of the student. • addQuiz - takes an int as argument indicating the score for a given quiz and adds it to the total score. Does not return anything. • getTotalScore - return the total score. • getAverageScore() - returns the average score. To compute the average, you also need to store the number of quizzes that the student took. Your class should pass the JUnit test provided. 9