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
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
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?
OR (these next two make real use Java and OO techniques)
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. :-)
OR
You could use Java's reflection package to achieve
method access by using the
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?)
(1)
(2)
(3)
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.
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)
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
(except that all must be Objects)