Modify the cannon ball in our cannon game so that:
The first thing I thought of was:
if ( deltaY > 0 ) // ADD TO public void move() color = Color.red; else color = Color.blue;
Why won't this work?
deltaY is private in class Ball, and color is private in class Disk -- as they should be.
The cannon ball needs to know if it is rising or falling. deltaY lives in the Ball class, so that class should have the code that answers the question.
The cannon ball needs to change to an arbitrary color. color lives in the Disk class, so that class should have the code that changes color.
So, I add a new method to the Ball class and a new method to the Disk class. Then I can change my solution to:
if ( yDeltaIsPositive() ) become( Color.red ); else become( Color.blue );
Take a look at the names I selected. The code reads in the same way that we think about the problem. That makes it easier to read and understand later.
Notice, too, that I added two methods to Ball. If this sort of behavior is useful in the vertical direction, then it might be useful in the horizontal direction.
Finally, when I look at Disk, I now realize that there is something important happening with color changes. This might lead me to change some things. Of course, because the protected methods shield the subclasses from Disk's implementation, any changes I make will not affect my other code.
Consider the 2D grid of Cells to the right. Suppose that the ends of the cross are the objects north, south, east, and west, and the object at the intersection is center. We can reach this configuration by making these moves:
west(right, x) south(up, o) west(right, x) west(right, o) south(up, x) west(right, o) west(right, x) south(up, o) south(up, x) north(down, o)
What is the value returned by each of these messages?
center.display('N') center.display('E') center.display('S') center.display('W')
Different orientations result in different values. Each object has multiple perspectives. This is true for people in 3D space as well. (Perhaps you have seen this famous New Yorker cover. The Pacific Ocean isn't north of New York City!)
What is we change the message to isStraight?
center.isStraight('N') center.isStraight('E') center.isStraight('S') center.isStraight('W')
How can center figure this out by talking only to its immediate neighbor?
How should we phrase the "tokens match?" question? Does it matter? It does. Think back to Arnold's coffee machine and the danger of asking too much. In design, it is better to have the message sender reveal the specific information needed to solve a problem that to have the sender request arbitrary information and then act on it. So have the cell ask its neighbor "do you match (my token)?" rather than "what's your token?".
Take a look at CellGridTest. There is something new there... CellGridTest has instance variables and a new method not named testX!
It is often helpful to write two or more tests that use the same objects set up in the same way. Rather than duplicate the set-up code in multiple methods, we can use JUnit's setUp().
As we have seen, JUnit runs each our our testX() methods, one at a time, and reports whether they pass or fail. If there is a setUp() method, JUnit runs it before running each test method, like this:
setUp() testX() setUp() testXX() setUp() testXXX() ...
That way, each testX() method executes in a "clean" configuration, with an identical configuration of objects and associations. These objects are stored in instance variables so that their values can be remembered between running setUp() and running testX().
Note: We don't know in what order the testX() methods will be run. Each test is independent of any other!
My tests for Cells create changes no longer than three. Maybe our solution doesn't work for really long chains.
Write a Java main() method that creates a chain of 100 Cells and checks to see if display works.
Bonus points: Don't use a Java array.
(Extra credit and no regular solution yet...)
Version 1: use an array.
It is a shame to hard-code the 100. We don't have to... We have args!
Version 2: use a command-line argument.
(What about those bonus points?)
Version 3: eliminate the array.
It's just a linked list from Data Structures.
Our cells allow single linked lists, but also double, triple, and quadruple linked lists. (That's what my 2D grid of cells is.) The way our Cell class is specified, we are not limited to two dimensions. We can build n-way linked lists for n/2 dimensions!
Looking good. What remains to fix or improve?
What's up with DefaultMemoDatabase:
Warning: /Users/wallingf/Desktop/session18/ memo-pad/DefaultMemoDatabase.java:17: warning: [unchecked] unchecked call to put(K,V) as a member of the raw type java.util.Hashtable
History. Collections of Objects.
Casting. Dissatisfaction -- C++ and Ada and ...
Java 1.5 added generics: "typed" collections.
private Hashtable<String, String> associations;
... and change in constructor. No cast required.