Interfaces as Callbacks
and why they are cool

A callback is a situation where you would like to pass a reference to some behavior and have another object invoke it later. (Like I wanted to do for the Timer class.) In C++, LISP, Smalltalk, one can do this via pointers or direct handles to these methods; in Java one way to do this is through interfaces.

First, in general:

Often there are classes that work a lot alike. In particular, their "interface" to the outside world would look the same. For example, for a video or audio interface, one might have init(), play(), stop() (or something like this). The Java Interface is like an abstract class that says what are the important methods All methods in an Interface are abstract (in an abstract class, one can have some methods that are not abstract). Also, any variables declared in an Interface must be static and final.

So, what about them?

Just like classes extend abstract classes to make them more "concrete", classes can implement interfaces. This means they have methods of the same name and actually implement the behavior for the method. (Note, since the methods are defined in a class that implements the interface, the methods actions can be particular to the class.)

Obviously video and audio equipment does something different when it plays(), but they use the same interface, simply different actions in eaches (respective) method play().

The book talks about graphics. I.e., one always wants to draw() objects, but depending on the object, it would be drawn differently.

Since Java does not allow passing of method names (discuss why), here is one way to get around explicitly changing code each time we time something.

Consider two classes: a Timer class that provides the running time of methods, and a RangeFinder class that determines the range of a given collection. We'd like our Timer to time any method. We could have RangeFinder store a reference to Timer.

We will define Timable as an interface and RangeFinder will implement it. An object that is an instance of RangeFinder will also be an instance of Timable (like inheritence).

(Also, this is Java's only sense of multiple inheritance - a (sub)interface can extend more than one interface)

Below are four options of doing a Timer. The last two are the best design for reusable object-oriented programming


(1)

implements "declares" object RangeFinder to be Timable - in doing so it "promises" to implement the timeMe() method

So, instead of a class Timer, have an interface Timable and actually time in the class where the method is... not at all a reusable Timer


(2)

OR (This choice is rather ugly and does not use nice OO techniques)

have the class Timer, but pass it more information and have the constructor determine data structure passed or somewhere do a case statement in the Timer (i.e., timer knows all methods it will ever be asked to time)

timer sends message to object passed saying time me (surrounded by all of the loops, etc). Here, timing actually gets done in the Timer class. It would be interesting to do the empty loop calling a method to a class that has a method that does nothing. Why?


(3)

OR (these next two make real use Java and OO techniques)

You could have an Interface Timable and have your classes implements Timable as above. But also have a class Timer with a method that is passed a Timable object. (If an object implements an Interface, Java recognizes that the object is one of those things. (instanceof the interface name even works) See
this interface page for more detail. Here, it is a much more beautiful use of polymorphism than the example just previous.


When you declare the RangeFinder object (in your PerformanceTester/RecordAnalyzer class), even if you declare it as a RangeFinder, java will still know it as a Timable instance since it implements Timable. If we only wanted it to know the Timable methods, then we would declare it as Timable but instantiate it as RangeFinder.
Note that the method in Timer is static, thus it can be called by the class.

Then

This is a cleaner technique since the Timer class never has to change. The only thing that needs to be done is if a class is going to have a method that needs to be timed, then it has to implement the Timable interface, which means implement the timeMe() method, and then in that method just call the method that that class wants to time. Pretty straight forward. :-)
If you wanted to time more than one method, you could perhaps make the Timable interface have a parameter (say an int - or a String (methodname)) for the timeMe() method (e.g., timeMe(int which)) and then the Timer has an extra corresponding parameter (e.g. timeThis(Timable whoToTime, int which)) ... and the timeMe(int which) method is passed this parameter, which then uses a case statement to determine which method in that class to time


(4)

OR

You could use Java's reflection package to achieve method access by using the invoke method on an Object. This is beyond the scope of this class (csci 311) but you can feel free to look into it (my notes from another class)


For more on Interfaces, see CoreJavaV1, Chapter 6 and Java in a Nutshell

Vector API and ArrayList API

Vectors and ArrayLists are dynamic arrays; they can grow to accomodate new items.

The Vector class works directly with the type Object - one can use them for instances of any kind of class (and varying classes!)

Insert and remove elements at arbitrary positions within it.

Careful - when take something out of a vector, we have to cast it back (narrow) it to its original type. This means your code must remember types or methodologically test them with instanceof.

(Also, cannot subclass Vector to make all of the same class. (Have ArrayList for all the same type.) Can make one that accepts a type-safe method at run-time, but it does not provide any new compile-time, static type safety)

Example:

things now contains three String objects in the order "one", "two", and "three" (remember - start at 0)

We can retrieve objects by their position as follows:

We have to cast each Object back to String in order to assign it a String reference.

We can also search for an item in a Vector with indexOf(whatever). It returns a value of -1 if the item (whatever) is not found.

contains() tests if an item is present

Also removeElement() and, of course, size()

Vectors: why are some methods synchronized? (what does this mean?)

For other useful data structures, see the collections page