Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Code reuse and object-oriented systems

Using a helper class to enforce dynamic behavior

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
In my last column, I demonstrated how to build a container using the container classes available in the standard Java distribution. That column ended with the building of a container, which was tested with a simple test application. What was left unspoken in the last column was a design decision to make the indexing key of our container a String object.

A String object was used because it has the property of being easily sorted. No other standard object in the Java standard libraries is both as flexible and as sortable as a string. We can't go ahead and make all keys in our container a subclass of String because String is final -- it can't be subclassed. Further, some objects work well as their own key, that can save space on the heap and garbage generation, both of which are Good Things. So what do we do? Well, let's see...

Solving the key dilemma

There are three approaches to solving the key dilemma. Each has its drawbacks, so one might conclude that there is no good solution. This is not true. A good universal solution may not exist, but there are widely applicable solutions.

The first approach: To everything Stringness

The first approach takes advantage of the fact that every object defines a toString method. This method is initially defined in Object but can be overridden by subclasses.

The toString method was designed so that all objects might have some representation that could be displayed on a character device such as a terminal or window. The number classes provide overridden versions that convert a subclass of Number to a printable representation. The default implementation in Object gives you the name of the object's class and its reference number (actually its address in memory) as a string. The format of the string is classname@hex-address.

With this knowledge, we can write a helper method -- stringForKey -- and then rewrite get, put, and remove to use this method on the key objects that are passed to them. The next bit of code shows both the helper method and the rewritten get that implements this solution:

private String stringForKey(Object o) {
        if (o instanceof String)
            return (String) o;
        return o.toString();
    }
    public Object get(Object skey) {
        String s = stringForkey(skey);        
        return search(rootNode, s).payload;
    }


In the code above, this version of the method uses the instanceof operator in Java to test if the key passed is already a string; if it isn't, it uses the toString method in Object to create a string for the tree. I have included a link to the source code of BinarySearchTree written in this way.

The advantage here is that, by default, all objects have an implementation of toString, and if this method is implemented in such a way as to uniquely define objects, we could certainly use it. Unfortunately, this solution depends on Java programmers knowing that this function may be used for this purpose. If a naive programmer were to design a class with an override of toString like that shown below, our search tree would be in big trouble.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources