Comp 170 Week 11
Point of Zuul: how do we get from the idea to the reality? For general programming, this is hard. But it is easier (not easy, but easier) to go from an idea for a Zuul room puzzle to an implementation of it.
Zuul 4.0
ValveRoom
DustyRoom
ZooRoom
DarkRoom
DarkRoom
Flashlight; Light generally
Note that an Item can now have added attributes besides its name! Yet TAKE, DROP still work without changes.
How class Light works, with (cast): occasional need for downcasting.
Casting
What if we wanted to do something CD-specific in the printing? Suppose we had a special method, printCD().
We could use
if (item instanceof CD)
item.print();
to print only the CDs. But if we try replacing print() with printCD(),
we get an error: the variable item has static type Item, even though we
know at this point that the
object it contains has dynamic type CD. We need a variable with static
type CD! We can't do "CD cd = item" either, because while that isn't a
mismatch, it goes in the wrong direction.
What we need is a cast:
if (item instanceof CD) {
CD cd = (CD) item; // the cast
cd.printCD();
}
Now what if we have our inventory, which is an ArrayList of Item, and
we want the flashlight, as a Light? We can find it easily enough with
Item.getByName(), but we then need a cast to convert it from Item to
Light. Note how those "extra fields" (that a Light has that an Item
doesn't) just get carried along for the ride.
class Light is cleaned up
Game.findByName is moved to Item.findByName
Linked-valveroom example
Player class version; Player holds:
- inventory
- currentRoom (because that's a player attribute!)
- isAlive (if you want it to be possible for the player to die)
Main change: the second parameter to Room.respond() is now Player p.
This isn't about support for multiple players; it's about the recognition that all the information for one player should be kept in a single place.
As part of basic hinting to the player, it is very important that all valid verbs be recognized as such in all rooms, even if they don't work there. For example, in the theater, if you type
GIVE COOKIE
the response is "You can't do that here" (emphasis added),
not "I don't know what you mean"
Wednesday:
Shapes lab, with MyShape base class
MyShape fields: xPosition, yPosition, color, isVisible. These are the attributes of any shape.
What methods moved to the base class?
- makeVisible
- makeInvisible
- moveRight
- moveLeft
- moveUp
- moveDown
- moveHorizontal(int distance)
- moveVertical(int distance)
- slowMoveHorizontal(int distance), slowMoveVertical(int distance)
- changeColor
- erase
(somewhat surprisingly, this is not shape-specific.)
A method belongs in a specific-shape class only
if it needs to be there; that is, if a general version can't be made.
There's no point to having subclasses if this isn't true for any
method, but often there's only one or two critical ones. The critical
ones here are draw() and changeSize().
Consider how the Picture class works: we create a bunch of specific shapes, add them to shapelist, and then draw each shape on shapelist. We could draw the shapes as we went along, but that wouldn't change the advantages of inheritance. One advantage of shapelist is that it allows us to redraw the whole picture, either to move it, or to "draw" it to a printer.
What if we tried to avoid MyShape, and simply tried to use the fact
that Circle, Rect, and Triangle are all subclasses of Object? The
problem here is that Object is too general: it has no draw() method. It
is critical that the base class we use is general enough to include
Circle, Rect, and Triangle, but specific enough that it has a draw() method (and all the other methods above).
Other possible MyShape subclasses:
Text
Polygon
Group
Note that if we were to define one of these, and include it in our Picture, the code that draws everything on shapelist would still work! No changes would be necessary to accommodate the new types.
Note also that we will never create a MyShape object; that is, an object whose dynamic type is MyShape, eg
MyShape s = new MyShape(...)
Such a thing could never be drawn, it is too general!
However, in Zuul 3.0, we do have a whole bunch of "general" rooms, of type Room: the Room objects provide "filler" and do not have special behavior.
MyShape is the classic objects-know-how-to-draw-themselves example.
protected v private
Square and Rect
In one sense, it is clear that a Square "is a" Rect, or "is a kind of".
However, there's an annoying issue here: you can take a square s, and
apply s.changeSize(4,7). It's now not square!
This is a fundamental problem, having to do with the idea that a Square is not a Rect with extra fields. It's a Rect with a constraint
on the existing fields. We need to be sure all mutators respect that
constraint, or are blocked (eg by "shadowing": redefining within Square)
Fox-Rabbit
Chapter 10
Run the simulation
Look briefly at the v1 code, and in particular at the Fox and Rabbit classes.
can we figure out the rules? Breeding is probabilistic. Locations of offspring is probabilistic.
version 2: the Animal superclass (just started Week 11)
Object
toString()
Go back to the Club example, in Membership.java
Add toString instead of print() to DoME?
Notice that this is yet another advantage of inheritance +
polymorphism: you can build in these predefined "hooks" into standard
libraries (like System.out.println())