Lecture 18
Recursion Review
We follow four basic steps when we design recursive objects:
- Define an interface with all of the methods that both base case and recursive case
classes must implement.
- Define one or more classes representing base cases. Make sure that all methods from
the interface are implemented. Convince yourself that the constructors and methods work correctly.
- Define the constructors for recursive classes. Recursive calls of the constructor
should only create objects that are simpler than the one being built by the constructor.
Similarly, instance variables whose types are either the interface or class should only
refer to objects simpler than the one being constructed. In particular, the construction
of simpler objects in the constructor body should eventually end up at a base case.
Convince yourself that the constructor will be correct under the assumption that the
construction of simpler objects is correct.
- Write each method under the assumption that it works correctly on all simpler objects.
Convince yourself that the methods will be correct under the assumption that instance
variables hold simpler objects.
Recursive Scribbler
We looked at writing a recursive version of our Scribbler program from earlier in the
semester. This program looked very similar to our bull's eye program, with a couple of
interesting differences.
The Scribbler recursive class constructor does not actually recursively call itself.
The recursive class does, however, declare an instance variable of the same type
that it is implemented by the class, which indicates recursion.
Also, the Scribbler program uses an empty base case. The base case does not necessarily need
to contain an object, but it needs to represent a simpler object of the same type. In this
example, an empty scribble is still a scribble.
The class example
SimpleRecScribbler
More Recursion
We looked at another recursion example where we had more than one recursively defined object
in our recursive case. In the broccoli example, a broccoli part consisted of a stem, and three
smaller broccoli parts. We handle them in the obvious way, and make sure to account for all
of them when defining our contains and move methods.
The class example
Broccoli
Next, we added some animation to our broccoli example. Instead of recursively calling
the constructor from the constructor, we called from the run method after
and appropriate pause. This slowed down the process of drawing the broccoli so that
we could see the recursion in process.
The class example
LivingBroccoli