Lab 1: Equality, Cloning, and Overriding

Goal

To introduce the students to the concepts and levels of equality, as well as the idea of cloning. In addition, to teach the basics of overriding, overloading, and the avoidance of code duplication

1  Let me say that again, Don't repeat yourself!

We'll be starting with the basics of function overloading, overriding and code reuse. To begin, please download the code and put it in a local folder on the machine you are using. The program is one that allows us to draw balloons to the console window and should compile as is. However, it will not work properly when it is run for a few reasons. The first part of this lab will examine the first of these reasons, the fact that the proper constructors have not yet been built.

We learned previously in 1101 how to make "cookie-cutter" constructors, and we will see how useful this really is in the grand scheme of our program design. Let's first implement a few constructors that will help us along the way. First, put the code in for our "cookie-cutter" constructor, which should have all the data we need to make the balloon. Please note when doing this that you should use the built in setX, setY, setRadius, and setColor functions when making the Constructor. Why you should do this will be shown later in the lab.

Let's introduce the basic concept of fuction overloading. We've actually done this quite a lot in the past but not given it a name. Function overriding is when two function have the same name, but are distinguishable by the types of parameters they take. Any time we make two constructors for the same class, we are overloading. So lets do this, make a copy constructor that takes another balloon and sets all the values of the balloon it is constructing to the ones held by the other balloon. Remember to use what you have done above!

Now for our final constructor. We know that Java gives us a default empty constructor as part of the Object class. However, this constructor may not do what we want it to. We may want to override the constructor in our Balloon class. Overriding is redefining a method previously implemented in a parent class to change its behavior. Override the default constructor so that it initializes a balloon to have a radius of 10, a location of 0,0, and a color of red.

Now we can run our program and it should "do the right thing"! Not only that, but we've condensed our code so that the internal representation of how the data is stored is only manipulated in a small number of functions, all those Sets and Gets. This allows for us to easily change the internal representation of how the information about a Balloon is stored without having to make large changes to the code. For example, think about what it would take to make the Balloon store the diameter internally rather than the radius. You may want to try changing this at home.

2  All Balloons are created equal, but which equal?

What does it mean to be equal? This question is one that has plagued computer scientists for years. If you have a twin brother, surely you are born "the same." But if he gets his hair cut short, your hair doesn't suddenly get short as well (wouldn't that be interesting!). In Java, when we check equality the "normal" way (using ==) the program verifies that the two items are the same. In other words, twins don't count! Java also treats the use of the = operator in the same way, assignment gives two different names to the same thing, changes to one affect changes to the other. We'll take a look at this first.

2.1  The cloning issue (a.k.a. a sheep named Dolly)

A lot of the time we don't want to use the = operator to refer to the same object, we actually want to create a new one and copy the values from the old one. This is what the cloneable interface allows us to do. In any class that implements this interface, the programmer should be able to say:

b2 = b1.clone();

Notice the issue with Balloon 0 and 2 in the BalloonView test. This is caused by a use of the = operator instead of the clone function. Write the code that allows for class Balloon to implement Cloneable and fix this test so that the Balloons are distinct from one another.

There are two ways that this can be done, each has its advantages and disadvantages. Between these two ways, and the usage of the basic = operator, their are three types sets that one can perform :

Assignment - The objects referred to are the same, they just have different names.
Shallow Cloning - The objects become distinct, but their member data is not cloned.
Deep Cloning - The objects become distinct, and all their member data is cloned as well.

The third option is most commonly the intention of cloning, in fact, if we use the second for our clone, our program will exhibit the same problems as before for everything outside of the radius of the balloon! Try implementing each and see how they work, and how they differ.

2.2  Comparing Comparisons

We know that using == works when we want to compare integers, doubles, or booleans. But does it do the right thing when we want to compare Strings, Balloons, or Goats. The answer to this is that most of the time, it doesn't! The == operator, similarly to the = operator, checks to see if these things are the same objects, not if they have the same values. In other words, if we use the clone method on an object, and compare the newly created one to the old one using ==, the program will tell us the two values are different. Most often, this is not our meaning. For this reason, Java has a method in the Object class, equals. However, this is the same as performing an ==. In order to get the result we want (one which tells us that two balloons with the same radius, x and y coordinates, and color are equal) we need to override the equals function.

Implement a new equals function that will work properly for our Balloons, and develop some tests.

3  Arrays are the thing in which we'll catch the problem with assigning

For the last part of the lab, we'll take a look at arrays, and all the problems it can cause with assignment. Please note, this section of the lab will only work if you have implemented the equals method for the Balloon class from the previous section.

Take a look at the arrayed balloon test, the purpose of this part of the assignment is to determine when the balloons within the arrays will be equal (as in equality by the equals method) and when they will be the same (as in they are two different names for the same object). Go through the commented out equality and == tests one by one, figuring out why the values should be what you predicted. When you're done and you run these tests, your program should not produce any output. If you predict the wrong value, an error message will be printed out.

Think about other tests like this that you could run (after all, thinking is what you are here for...). Would it be possible to design a test where the objects are equal using == but not equal using the equals method? Why is this true? Also, are we guarenteed that if == returns true, that the objects are identical, are we guarenteed that if == returns false, that the objects are different? Explain and defend your answer.