Revisit A04, only this time make the sphere its own class and create instances of it.
Concepts: Constructors, instance variables, encapsulation
Textbook: 4.1 - 4.3, 4.5
You are going to create a Sphere
class, test that it is correct, and then use that class to solve a problem involving planets. Do this in the following order.
Sphere.java
Write a public class named Sphere
. Put this in its own file (for now). The class should have at least one private
instance variable for the radius. The class should also contain the following public constructor and methods:
Your methods must much these signatures exactly (though you can change the variable name r
, if you like). Note how, unlike in A04, the methods not static
and the get methods no longer take parameters. This is because every sphere now already knows its own radius, 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 or ask for any input from the user.
Error-checking of passed values is optional. For example, you could prevent negative values for the radius by setting it to 0 or taking its absolute value instead; but this is not required--you can allow another programmer to make a cone with a negative radius if they really want to.
The primary reason for writing methods is so that you can easily reuse chunks of code. It reduces errors and makes code easier to maintain if you can avoid duplicating code.
But the separation of code into small, independent modules has additional benefits. It can make the code more readable overall. And you can then unit test each of these small pieces to know they are correct. This helps greatly when debugging, especially for larger programs.
Here is a sample unit test for your cone: SphereTester.java.
Download this file and put it in the same directory as your Sphere.java
file. You should then be able to compile and run SphereTester
to ensure that all your methods have the correct signatures and return the correct values. Take a look at how the SphereTester works because you will be responsible for testing your own classes in future assignments.
UsernameA10.java
)Now that you know your Sphere is correct, you could reuse it in a number of different programs. Here is one such program:
The four terrestrial planets in our solar system include:
Planet | Mean Radius (km) | % of Earth's radius |
---|---|---|
Mercury | 2440 | 38 |
Venus | 6052 | 95 |
Earth | 6371 | 100 |
Mars | 3386 | 53 |
Assuming these planets were perfect spheres, write a program that clearly prints the radius, surface area, and volume for each of the four terrestrial planets. For each measure, also indicate afterwards on the same line what % this is of Earth's measure. Print this % as an int. (Round it with Math.rint
; don't just cast it. And remember to include the % sign.) Use your Sphere class for all calculations, so that the only literals you will have in main will be the radii given above.
There is no user input for this program. Note that you may not need to call every Sphere method to solve this particular problem.
Dimensions of the 4 terrestrial planets (as % of Earth's): EARTH Radius: 6371.0 km (100%) Surface Area: 5.1006447190978825E8 km^2 (100%) Volume: 1.0832069168457537E12 km^3 (100%) MERCURY Radius: 2440.0 km (38%) Surface Area: 7.481514408964877E7 km^2 (15%) Volume: 6.0849650526247665E10 km^3 (6%) ...
This is only the first half of the output, just to show you a sample format that meets the requirements. You'll need VENUS and MARS as well. Planet order is up to you.
If you want to format the long doubles for printing, please still include at least 3 digits 4 digits after the decimal point.
You are going to submit only your UsernameA10
and Sphere
classes.
Normally, each Java class should be in its own file. However, Tamarin only takes a single file per submission. So you are going to move your Sphere
class into your UsernameA10.java
file. Paste the entire Sphere
class after the last } of the UsernameA10
class. (Please make sure you don't put one class within another!)
Java will allow you to have only 1 public class per file though, so you also need to remove the word public
from the Sphere
class. (Leave the public modifier on all your methods, though.)
So, your UsernameA10.java
file should now be structured like this:
public class UsernameA10 { //... your main method in here ... } class Sphere { //... your sphere methods in here ... }
You may want to try deleting all your .class files, and then compiling and running your UsernameA10.java one more time before you submit it, just to make everything still works correctly.
Then, upload your complete UsernameA10.java
file to Tamarin.
Sphere
Constructor
Sphere
accessor (get) and mutator (set) methods for radius
Sphere
accessors for diameter, circumference, volume, and surface area.
UsernameA10
HighScore
--from the first lab this week. It has been expanded and commented to show the encapsulation principles at work.
Then, to show how such a class might be used, see ArcadeGame.java
UsernameA10
class. Then you only have to write this code once, and can then just call the method four times, passing the method a different planet/sphere to work with each time. Since all the code then occurs only once, you only have to write it once. Also, it is much easier to correct and maintain, rather than trying to fix 4 different copy-and-pasted versions.
So, for example, you could write a method like this:
public static printPlanetDetails(Sphere planet, Sphere basePlanet)
In this method, print out the radius, surface area, and volume of planet
. Also calculate the % of each in terms of basePlanet
. Then, in main, after you create the 4 planet Spheres, you can call this method like this:
System.out.println("EARTH"); printPlanetDetails(earth, earth); System.out.println(); System.out.println("MERCURY"); printPlanetDetails(mercury, earth); //...
This will save you a fair amount to editing/code tweaking time. Note too how easy it would then be to change your program later to include more planets, other planets, or determine the %s based on a planet other than Earth. This is the advantage of breaking your code into methods instead of manually duplicating code. (Note how the SphereTester class above did the same sort of thing.) This example also demonstrates how you can pass whole objects around to other methods.
printPlanetDetails
method descibed above can print to the screen? Shouldn't methods just return their results?
On the other hand, sometimes you just want to move code out of main
into a separate method. This serves two purposes. First, it can make main easier to read. Instead of a big block of code, there is just a single method call:
System.out.println("EARTH"); printPlanetDetails(earth, earth);
This makes is easier to quickly understand what main
is doing. Then, to see the particular details of how planet details are printed, you can go look at that method.
The second purpose of moving code from main into a method is that you can then easily repeat that code by calling the method a number of times. This is certainly true for printPlanetDetails
.
So, since printPlanetDetails
is helper method to main
and its purpose is to help you generate output, it is fine to let it print to the screen for you.
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 Sphere after you construct it, or to ask a Sphere object what its 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 change 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 Sphere; 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 Sphere; instead, they can only change the radius.
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.
getCircumference()
and getDiameter()
methods? They aren't necessary for the planets problem.
If the planet's problem were instead the focus of A10, then you'd probably write a Planet (rather than Sphere) class and then you would not need to implement any methods you weren't going to use for that particular assignment. (However, while designing such a Planet class, you would still want to think about additional ways a Planet might be used so that your design would allow for easy expansion if it ever was reused elsewhere.)
If you're using a DecimalFormat
object to format your doubles, the format string you select will produce very different output. Here are some examples when formatting the double values 1.0832069168457537E12 and 5.1006447190978825E8 (Earth's volume and surface area).
Format | Sample Output | |
---|---|---|
# | 1083206916846 | 510064472 |
#.### | 1083206916845.754 | 510064471.91 |
0.000 | 1083206916845.754 | 510064471.910 |
0.###E0 | 1.083E12 | 5.101E8 |
0.0000E0 | 1.08321E12 | 5.1006E8 |
The # means a number, which can be dropped/not displayed if it is 0. Using 0 instead forces that digit/number to be displayed, even if it is 0. What Tamarin is searching for is the 0.000 prefix, assuming the numbers are displayed in the E format. Since DecimalFormat rounds for you, you should actually use "0.0000E0"
as your formatting string to avoid any problems.
But, like I said, as long as your results are correct, I'll correct Tamarin if it's just failing due to format.