Writing an instantiable class

In this lab, you will write an instantiable class (i.e., a class for making objects) and use it in an application class (the "main" program).

As always, create a new folder for this lab. Download Dairy.java into it.

Creating a custom-made instantiable class

Think of Dairy as a custom data type. The Dairy.java file will define the rules for how all Dairy objects behave. Such a class is known as an instantiable class.

The line that says public class Dairy { begins the class definition. All of the variables and methods for this class will be defined somewhere within that code block.

The first 3 lines are a Javadoc-style comment describing the purpose of the whole class.

Dairy class declaration

Immediately after the line public class Dairy {, we declare any variables that represent the current internal state of a Dairy object (these are called instance variables). Internally, a Dairy object needs to keep track of the number of cows on a dairy farm. Remove the TODO comment and declare an int variable to store the current number of cows. Don't write a main method in this class. If you try to compile at this point, it should complain about a missing return statement, which is because we haven't filled in getNumCows() yet.

It is a good idea to get into the habit of commenting your instance variables. Add a single-line comment (not javadoc style) saying what your represents (i.e. the number of cows on the farm).

Now fix the compile-time error by having the getNumCows() method return your variable which keeps track of the number of cows. Then remove the TODO comment.

getNumCows method

Next we will discuss how to write a constructor for this class. The constructor contains any code that gets executed when a Dairy object is first created (see code fragment below).

Dairy class constructor

The Javadoc-style comment here describes what this constructor does. The constructor is public because we want to be able to use it from other .java files. The word public is followed by the class name (in this case, Dairy), and a pair of parentheses () containing a list of any parameters that need to be supplied by the caller (in this case, just the initial number of cows).

Remove the TODO comment and replace it with a statement that sets the number of cows equal to initialCows. You are doing this because parameters such as initialCows only exist temporarily, for the duration of the constructor call (or method call). But you want to copy in the value provided into a persistent storage location: the instance variable you declared earlier.

Let's add one more method. It should be a (non-static) void method called addCow. It should take no parameters and should simply increase the number of cows by 1. Note that instance variables are available to be used or modified in any method of the class they are defined in (technically, any non-static method). Don't forget to add a Javadoc comment for it.

Using the Dairy class in an application

Now we have written just enough to make using the Dairy class interesting. Create a second .java file, called MainApp.java. This will be an application class - the same kind you have been writing all semester. After writing the basic structure of MainApp.java, add a little code to test out if the Dairy class works correctly:

		Dairy f = new Dairy(3);
		int c = f.getNumCows();
		ConsoleIO.printLine("There are " + c + " cows on farm f.");

		Dairy d = new Dairy(2);
		c = d.getNumCows();
		ConsoleIO.printLine("There are " + c + " cows on farm d.");

Compile and run MainApp.java, and make sure it does what you expect. Notice how f and d are both Dairy objects, but they have different numbers of cows. Now add a little more code: call the addCow method twice on f and print out the number of cows that results (don't modify the addCow method you wrote earlier, just call it twice). You should find that it reports there are 5 cows after this happens.

You have just written a simple instantiable class and used it in an application class. Now we will add more interesting features.

Making additions to your instantiable class Dairy

  1. Write a second constructor for your Dairy class. This one should take no parameters as input, and should set the number of cows to zero. Write a Javadoc comment for this constructor. In Java, it's ok to have multiple constructors like this, as long as the number and/or data types of the parameters vary, so it can tell from context which one is being called (this is called constructor overloading).

    "I'm having trouble getting this constructor to compile."

  2. Write a second addCow method, but this time it should take a parameter indicating how many cows are to be added. We already have a method called addCow, but Java will be able to tell which one is being called by looking to see whether or not an int is being supplied as an argument to the method call (this is called method overloading, and it works the same way as constructor overloading). Write the Javadoc comment for this method - don't forget to include the @param tag to indicate what the input parameter represents.
  3. Write a method called calcMilkProfit. It should take a double as a parameter (the price per gallon) and return a double (the amount of profit, for the entire herd). To calculate the profit, use the given price per gallon and assume that each cow produces 10 gallons of milk. Write a Javadoc comment for this method, including the @param and @return tags.
  4. Write a method called calcButterProfit. It should take a double as a parameter (the price per pound) and return a double (the amount of profit, for the entire herd). To calculate the profit, use the given price per pound and assume that each cow produces enough milk for 4 pounds of butter. Write a Javadoc comment for this method, including the @param and @return tags.
  5. Fix up your indenting in Dairy.java, if necessary.

Writing another application class that uses the Dairy class

Write a second application class called Farm.java, which creates a Dairy object using the no-parameter version of the construtor. Then make a call to addCow, supplying 5 as an argument. Using a call to calcMilkProfit, print out the amount of profit if we decide to sell as milk, at $1.10 per gallon. Similarly, print out the amount of profit if we decide to sell as butter, at $2.50 per pound. Now add 5 more cows and print out the butter and milk profits again, at the same prices per gallon (or pound). It should look something like this:

Profit from milk, for 5 cows: $55.0
Profit from butter, for 5 cows: $50.0
Profit from milk, for 10 cows: $110.0
Profit from butter, for 10 cows: $100.0
"Why am I getting something like 50.000000000001 instead?"

Check your work

  1. Are you getting the same answers as you see above?
  2. The actual calculations for milk and butter profit should all be in the Dairy class, not in main.

When you are done, hand in all 3 .java files.