Session 12

Going Deeper into an OO program, Part 2


CS 2530
Intermediate Computing


Figuring Out the BallWorld Program

Answer these questions about BallWorld:

Modify the color of the ball to be green, not red.
Modify the ball to be much larger and to move much faster.

...

Modify the simulation so that it runs much longer.
Modify the shape of the window to be 100 X 800.

...

Why not use a Point to represent the Ball's location?
Why not make "BallWorld" a symbolic constant like FrameWidth?

This can be a useful way to learn a program. Read it. Run it. Imagine changes or additions, and then figure out how to make them work.



Where Are We?

Last time, we did two things. First, we finished off our design for Arnold's coffee machine by finally creating an object for the product being sold. One of the key lessons of that case study is that, in an OO program, almost everything should be an object.

Second, we began to go deeper into our second program, BallWorld. It is a simple program that brings to our attention some of the issues we face when turning a design idea into a Java program.

BallWorld creates a window that contains a ball that "flies" through the window for a brief moment and then stops.

Here are a few screenshots taken in sequence:

first snapshot second snapshot third snapshot fourth snapshot

In last session's notes, I said a couple of things you might have thought inaccurate. I said that that BallWorld contains a ball that...

Don't settle for reading the code when you can run it! The converse is usually also true. Don't settle for running the code when you can read it, too.

(Side note: If you would like to slow the program down, insert this line after incrementing the counter:
    try { Thread.sleep( 200 ); } catch (Exception e) {}
You can experiment with different numeric arguments. We will talk about how this line of code works in a few week.)

A BallWorld consists of two user-defined objects created from three user-defined classes. Last session's notes considered each, pointing out some of the salient features of the class and some new Java features.

What questions do you have about BallWorld: at this point?

Let's answer those questions, as well as some others, about two key issues of OO programming in Java: constructors and inheritance.



Constructors

In Java, a constructor guarantees that objects are into a legal initial state from the moment they are created. A constructor like other methods, with two differences: its name is identical to the name of the class, and there is no return type. No piece of code can execute a constructor except by creating a new instance.

There are three constructors in this program, one each in Disk, Ball, and BallWorldFrame. Each is invoked exactly once:

The last of these is an implicit invocation. Let's save talking about it for a few minutes.

A constructor is a method that combines two essential activities in any program: creating an object and initializing the object. From the OO designer's perspective, object creation and initialization are intimately tied together. Objects are independent collaborators in our programs. When we create an object, we want it to be able to participate in the program immediately. It's good that Java enforces this connection. Otherwise, we could create an object and try to send it a message before it is initialized.

... allocates memory. At run-time, an object resembles constructs you have see in other languages, such as a record or a structure.

... assigns initial values to all the slots. All Java variables are initialized, either explicitly by the program or implicitly by the run-time system. As a matter of practice, in this course we never rely on implicit initialization.

The operator new is used to create a new object. This operator is always followed by a class name, which indicates the kind of object being created, and a parenthesized list of zero or more arguments used by the constructor to initialize the new object.



Inheritance

The most important new object-oriented feature of this program is its use of inheritance. Both of the primary objects in this program are defined using this technique.

A Ball is a kind of Disk. A Disk is also a user-defined class. Like Disks, a Ball will draw itself on the screen in response to a paint() message. Unlike Disks, though, a Ball

will also respond to a move() message, by changing its location.

... inherited instance variables.
... inherited constructors, to initialize them.
... the special variable super.

Note: Even if our class definition does not say so, the first thing done by a Java constructor is to invoke an inherited constructor. If we don't explicitly invoke super(...) as the first line, the Java run-time system will invoke the default super() constructor. So, always make a call tosuper(...) the first line in every constructor you write.

... inherited methods.
... thus a Ball can paint() itself.
... the access modifier protected.

... conundrum:protectedinstance variables?
... All instance variables are private. really.
... if necessary, provided protected accessors.
... but may not be necessary, as with Ball.

If you have a Disk variable, you can store a Ball in it and send it messages -- but only the messages that a Disk responds to. Java is strongly typed in this sense.

A BallWorldFrame is a kind of Frame. A Frame is a Java library class. Like Frames, a BallWorldFrame make itself visible on the screen in response to a setVisible(true) message. It can also repaint() itself and changes its title (setTitle()) and dimensions (setSize()).

Unlike Frames, though, a BallWorldFrame paints itself in a very specific way...

We can observe other inherited behavior in running program. We can move, resize, maximize, and minimize the window, even though the class does not explicitly define code to provide these behaviors. You'll notice that the superclass does not provide all the behavior we might expect: the window will not close itself when we click that button. That behavior is disabled in the inherited method!

(Now you know why our memo pad and calculator apps provided a CloseableFrame class and had their frames extend it. We learn how to write classes such as CloseableFrame in coming weeks.)

The code necessary to do even simple graphics of this sort in a modern operating systems with a modern graphical user interface is quite complex and long. Java provide a multitude of graphics classes as a part of its standard library, which we then reuse by inheritance and instantiation. As a result, we don't have to concern ourselves with system-level details and can focus on the features of our application. I often wish some of my other favorite languages did the same!

My Disk does not have an extends clause. Even so, it inherits from an existing class, Object. This root of all classes provided basic behavior that every object needs to have. We have seen two already, toString() and equals(). You have written a method that replaces the inherited behavior for toString() in one of your classes, and in a few weeks we will learn how to "override" the inherited behavior for equals().



Wrap Up



Eugene Wallingford ..... wallingf@cs.uni.edu ..... October 2, 2012