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

Page 2 of 7

    public String toString() {
    return "A Foo Object." }


The method shown above is a perfectly legitimate implementation of toString according to the Java language specification, and yet it has the annoying side effect of causing objects of this type to be non-sortable. Every instance of this object type will return the same string representation and thus will not be distinguishable in the BinarySearchTree code.>

A second approach: Interfaces

The issues involved in using toString can be evaluated in The Java Language Specification by James Gosling, Bill Joy, and Guy Steele. Taken from the specification, the contract for toString is as follows:

"The general contract of toString is that it returns a string that 'textually represents' this object. The idea is to provide a concise but informative representation that will be useful to the person reading it."


As you can see, the specification doesn't say anything about being unique across object instances.

To get the guarantee that the programmer will know what we wanted for our keys, we can define an interface to provide a contract where Object did not write into the contract that toString could be used as a unique key. This way, we can make the contract for that interface clear to its implementers. The canonical example is to define an interface, ours is named SearchKey, that defines the contract for a key used for searching. The code for SearchKey is shown below.

public interface SearchKey { 
    /**
     * returns < 0 if search key o is less than this object. 
     *           0 if search key o is equal to this object. 
     *         > 0 if search key o is greater than this object. 
     */
    abstract int compareKey(SearchKey o);
    /** Return true if passed Search Key matches this one */
    abstract boolean equalKey(SearchKey o);
}


This interface defines the method compareKey to have semantics that are equivalent to the compareTo method in class String. I avoid reusing the same, or common, method names in the interface definition as Java is unable to distinguish between two methods with the same signature in two separate interfaces. It is poor form to choose method names that might easily collide with other interface definitions. The second method returns a boolean value indicating that two keys are equivalent.

The contract, then, is that any object implementing this interface can be used as an index key to our container. The most common implementation of equalKey might be similar to the code shown below.

public boolean equalKey(SearchKey o) {
    return (compareKey(o) == 0);
}


The interface explicitly calls out the requirements of its implementation. Therefore, programmers implementing this interface in their objects will understand the underlying contract between the container and its keys. By combining the two methods equalKey and compareKey, the invariants of the binary tree search algorithms can be maintained.

Using this interface in our container is a bit more difficult. We cannot change the method signatures of get, put, and remove, as they are constrained by the Dictionary superclass. However, we can force an error if the client fails to abide by our rules. As in the first approach, we define a private helper method to convert from the Object class reference to a SearchKey reference. This method is called keyForObject and it is shown in the code below.

  • 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