Copyright © Cay S. Horstmann 2009, 2012
This work is licensed under a Creative Commons
Attribution-Noncommercial-Share Alike 3.0 United States License.
See lab 1 for reporting instructions.
The steps tagged with this icon are optional. Do them if you have time and want to practice more.
A. A Car class
Car
class that simulates a car.
The class has methods for adding gas, checking the gas level, driving for a
number of miles, and checking the odometer (i.e., total miles driven).
Let's deal with adding gas first.
What should the following program print?
/** This program tests the Car class. */ public class CarTester { public static void main(String [] args) { Car myHybrid = new Car(); myHybrid.addGas(20); myHybrid.addGas(10); double gasLeft = myHybrid.getGasInTank(); System.out.print("Gas left: "); System.out.println(gasLeft); } }
car
and classes
CarTester
and Car
.
In the tester program, add a line
System.out.println("Expected: ...");
where you replace ...
with the value that you expect (from
step 1).
Start out with this Car
class:
/** A car can drive and consume fuel. */ public class Car { /** Constructs a car. */ public Car() { } /** Adds gas to the tank. @param amount the amount of fuel to add */ public void addGas(double amount) { } /** Gets the amount of gas left in the tank. @return the amount of gas */ public double getGasInTank() { return 0; } }
Now run the tester program. (Right-click on the CarTester
class and select main
.)
What output do you get? Why don't the actual values match the expected values?
Car
object needs to have a way of
remembering the amount of gas in the tank. An object uses instance
variables to remember information. Add an instance variable as
follows:
/** A car can drive and consume fuel. */ public class Car { private double gasInTank; /** Constructs a car. */ public Car() { gasInTank = 0; } /** Adds gas to the tank. @param amount the amount of fuel to add */ public void addGas(double amount) { } /** Gets the amount of gas left in the tank. @return the amount of gas */ public double getGasInTank() { return gasInTank; } }
Now run the tester program.
What output do you get? Why don't the actual values match the expected values?
addGas
method. Adding gas to
a car is pretty much the same as depositing money in a bank account. Look
into section 3.5 of your textbook and locate the
deposit
method.
What is its code?
balance
is an instance variable in the
BankAccount
class. Each bank account remembers its balance.
What is the analog of balance
in our
Car
class?
deposit
method, how do
you implement the addGas
method?Add these calls to the end of the CarTester
class:
myHybrid.drive(200); myHybrid.drive(100); double milesDriven = myHybrid.getMilesDriven(); System.out.print("Miles driven: "); System.out.println(milesDriven);
What do you expect these lines to print?
Car
class:
/** Drives a certain amount, consuming gas. @param distance the distance driven */ public void drive(double distance) { } /** Gets the total miles driven by this car. @return the miles driven */ public double getMilesDriven() { return 0; }
Compile and run the tester. What happens? Why?
What do you need to add to the class so that it can remember?
milesDriven
instance variable, set it to zero in the
constructor, return it in the getMilesDriven
method, and
update it in the drive
method.
What changes did you make to the code?
/** This program tests the Car class. */ public class CarTester2 { public static void main(String [] args) { Car myHybrid = new Car(); myHybrid.addGas(20); myHybrid.drive(200); myHybrid.drive(100); double gasLeft = myHybrid.getGasInTank(); System.out.print("Gas left: "); System.out.println(gasLeft); } }
Compile and run this tester. What happens?
Let's say the car has a fuel efficiency of 50 miles per gallon. How much fuel does it consume when it drives 300 miles?
System.out.println("Expected:
...")
line to the end of CarTester2
.
What line did you add?
Car
class do you need to modify so that the car behaves
correctly?double gasConsumed = distance / efficiency;
to the drive
method in the Car
class.
Compile. What error do you get?
private double efficiency;
to the top of the Car
class.
Compile and run CarTester2
. What
happens?
Set efficiency
to 50 in the constructor.
Compile and run CarTester2
. What
happens?
Car myGuzzler = new Car(10);
Change the constructor of the Car
class to
/** Constructs a car with a given fuel efficiency. @param anEfficiency the fuel efficiency of the car */ public Car(double anEfficiency) { gasInTank = 0; milesDriven = 0; efficiency = anEfficiency; }
Now compile CarTester2
. What happens?
Why?
CarTester2
so that it again
passes the test?B. A Car with Alice and Netbeans
Car
class
that you wrote in part A.
Then change the first line from class Car
to class
Car extends RedRover
(Alice 3.1 doesn't have a model of an actual car, so I picked this one instead. You'll see presently how it looks.)
In myFirstMethod
inside the Scene
class, add
these lines:
Car myRover = new Car(50); myRover.setVehicle(this); // Needed to make the car appear in the scene
Then run the program.
What happens?
myFirstMethod:
myRover.drive(100);
Then run the program.
What happens?
drive
method of Car
, add a call
move(MoveDirection.FORWARD, distance / 100);
This will make the car move. We divide by 100 so that the car doesn't leave the screen.
Run the program. What happens?
myRover.say("Gas: " + myRover.getGasInTank());
at the end of myFirstMethod
.
Run the program. What happens?
myRover.setVehicle(this);
myRover.setOrientationRelativeToVehicle(new Orientation(0.0, Math.sqrt(2) / 2, 0.0, 1.0));
Run the program. What happens?
C. An Optional Gas Gauge
ColaBottle
.
Add this import statement to Car
:
import org.lgna.story.resources.prop.ColaBottleResource;
Add this instance variable to Car
:
private Prop gauge;
Add this code to the Car
constructor:
gauge = new Prop(ColaBottleResource.COLA_BOTTLE); gauge.setVehicle(this);
Add this line to the drive
method:
gauge.turn(TurnDirection.BACKWARD, gasConsumed / 10);
As always, don't worry about the Alice magic. You will never be asked to memorize or create it.
What happens when you run the program?
Ok, you peeked. Here is the outline.
DoTogether.invokeAndWait( new Runnable() { public void run() { move(MoveDirection.FORWARD, distance / 100); } }, new Runnable() { public void run() { gauge.turn(TurnDirection.BACKWARD, gasConsumed / 10); } });
You also need to declare the variables used inside the run
methods as “final”:
public void drive(final double distance) { final double gasConsumed = distance / efficiency; ... }
I won't explain this—you'll learn more about it in CS151.
Try it out. How is this different?