Assignment 10

Task

Repeat A09, only this time using instance variables for the radius and height.

Concepts: Constructors, instance variables, encapsulation
Textbook: 4.1 - 4.3, 4.5

Steps

You are going to modify your original SphericalCone class, test that it is correct, and then use that class to solve the same problem involving ice cream cones from A09. Do this in the following order.

Step 1: SphericalCone.java

Write a public class named SphericalCone. Put this in its own file. The class should have at least two private instance variables for the radius and height; you may have more if you wish. The class should also contain the following public constructor and methods:

Your methods must much these signatures exactly (though you can change the variable names r and c, if you like). Note how, unlike in A09, the methods no longer take parameters. This is because every cone now already knows its own radius and height, so you don't need to pass this information to the methods anymore.

Your methods should return the correct values. They should not print anything to the screen.

Step 2: Tester (UsernameA10b.java)

You now need to write a unit test for your revised SphericalCone class.

Recall you used a sample unit test for your cone for A09: SphericalConeTester.java. You can use that as a template for your own unit test for this assignment; or you can simply write your own from scratch.

The tester should construct a SphericalCone and call all of its getter methods. It should compare each returned value with the expected correct value. The output should clearly indicate whether each test was a success or not. If the test failed, you need to show both what was expected and what was actually returned. (You can print this information for successful tests too, if you like).

Then you also need to test the two setter methods. To do this, you need to set one of the dimensions of the sphere object to a new value. Then call the associated getter and check if you get the new value back. (Note that you may also want to test your other get methods again too. With some implementations, you may find that the values returned by these methods did not change properly when the underlying cone dimensions were changed.)

Note that you can no longer use the default constructor and calls to getSlantHeight, getVolume, and getSurfaceArea no longer require parameters. Though it is good practice to do so, you are not required to handle the minor potential difference between doubles; you can just compare them using == if you want to.

Your test program should take no user input.

Step 3: Main program (UsernameA10a.java)

Now repeat the main program of A09 with your new SphericalCone. Use the same dimensions:

Clearly print the surface area and volume for each of these three spherical cone sizes, as well as the total volume.

There are two general approaches to this problem: you can either create 3 separate cone objects, or you can create 1 cone and change its size in order to get the different results.

There is no user input for this program.

Sample Output

SMALL cone:
Volume = 68.48657702033661 cm^3
Surface area = 100.88951136341649 cm^2

MEDIUM cone:
Volume = 118.34480509114118 cm^3
Surface area = 145.28089636331964 cm^2

LARGE cone:
Volume = 353.95277230445 cm^3
Surface area = 285.8849314766712 cm^2

Total volume: 540.7841544159278 cm^3

What to Submit

There are two submissions for this assignment. Remember what you learned about putting two classes in a single file from A09.

Upload your UsernameA10a.java file to Tamarin. This file should contain your main program class (public) and your SphericalCone class (not public).

Then upload your UsernameA10b.java file to Tamarin. This file will contain only your testing class.

Grading [7 points] (2 parts)

UsernameA10a.java

1 - Compiles
Your program compiles successfully (no errors). Also, SphericalCone methods and constructor should not print to the screen.
0.5 - SphericalCone Constructor
Has a public constructor that takes two doubles (radius and height, in that order).
1 - SphericalCone accessor (get) and mutator (set) methods for radius and height
0.2 each for two get methods; 0.3 each for two set methods.
1.5 - SphericalCone accessors for slant height, volume, and surface area.
0.5 each. All methods are instance methods (not static) and exactly match the method signatures given above. Returned values are correct even after changing the dimensions of the cone using the set methods.
1 - UsernameA09
Program clearly prints the correct volume and surface area of the three cones (small, medium, large) with the dimensions given above (0.6). Also prints the total volume of the three cones (0.1). Creates and uses at least one SphericalCone object to do this (0.3).

UsernameA10b.java

1 - Compiles
Your program compiles successfully (no errors) when combined with a SphericalCone that matches the above requirements.
1 - Tests all methods
Calls each SphericalCone method at least once (0.7). Calls at least getRadius and getHeight methods again after calling set methods (0.3). Points (up to 0.5) may be deducted if the output of the tester is unclear: no way to tell if a test passed or failed, no feedback of what's wrong when a test does fail, etc.

FAQs

Why do we have to write the getRadius() and setRadius(double r) methods? Same for the getHeight() and setHeight(double c) methods.
It's to practice encapsulation.

You should make your instance variables private. When you do this, you can no longer affect them directly from another class. But it'd still be nice to be able to change the size of a cone after you construct it, or to ask a cone object what its height or radius is. So you write a couple public methods that lets other classes affect the instance variables only through those methods.

This practice of encapsulation is a good long-term programming practice for large projects. Making your instance variables private means you effectively hide them so you can later make changes to how your class works internally without having to also change all the code in every class that uses that changed class (since they use only the methods). An example of this is that your accessor methods for volume and surface area may hide the fact that you don't even have a variable for those dimensions of the cone; instead, you simply calculate them each time the value is requested through the accessor method.

Also, you can error-check any changes someone is making to a variable in the mutator method. For example, you could enforce in your setRadius method that no one ever sets the radius to a negative value. This is something you could not control if another class had direct access to the variable.

Finally, you could prohibit changes to some variables all together by simply not writing a mutator method for it. For example, no one can directly change the volume of your SphericalCone; instead, they can only change the radius or height.

So, for all these reasons, encapsulation is good practice--particularly for large projects where you have 10s or 100s of classes. So that's why we're having you do it here--to get into the habit.