Interactive Programming in Java

Lynn Andrea Stein · 2003

int getValue(); } That's all there is to it. Q. In this definition of Counting, the word abstract appears twice. In the previous definition, above, it doesn't appear at all. Explain. In fact, that was so easy, let's try another interface. This one is Resetable, and it is a very simple interface. (Good interfaces often are.) Resetable has a single method: interface Resetable { abstract void reset(); } This interface is fine, but it could do with a little bit of documentation. After all, 4.3 Interface Declaration 4~13 IPIJ || Lynn Andrea Stein there are many things that an interface doesn't specify. Q. Can you identify some things that should be included in Resetable's documentation? For the precise specification of what may be included in an interface definition, in what order, and under what circumstances, see the Java Chart on Interfaces. 4.3.2 Method Footprints and Unique Names It might seem that each method in an interface would have a unique name. However, it turns out that this isn't the case -at least, not exactly. Instead of a unique name, each method in an interface (or class) definition must have a unique footprint. The method's footprint consists of its name plus its ordered list of parameter types. Only the ordered list of parameter types counts; the return type of the method, and the names given to the parameters, are not relevant to its footprint. For example, a reset() rule with no parameters (an empty parameter list, () ) has a different footprint from a reset( int newValue ) rule (with the parameter list (int) ), and both are different from reset( String resetMessage ) (parameter list (String) ). Only the parameter type matters, though, not the parameter names: reset( String resetMessage ) is the same as reset( String whatToSay ). As long as two methods have different footprints, they can share the same name. This is very common and even has its own name: overloading. Overloading allows an object to have two (or more) similar methods that do slightly different things. For example, there are two very similar mathematical rounding methods. One has the signature int round( float f ); while the other has the signature long round( double d ); The Math object has both of these methods, and if you pass Math.round a float, you get back an int, while if you pass it a double, you get back a long. This is very convenient -in both cases, a floating point number is converted to an integer, but in either case the more appropriate size is used. An alternate kind of overloading might happen if our hypothetical AlarmedCounting interface had, in addition to its void setAlarm( int whatValue, String alarmMessage ) 4~14 Specifying Behavior: Interfaces Chapter 4 IPIJ || Lynn Andrea Stein method, a second method that just allowed you to specify the alarm message, without changing the value for which it was set: void setAlarm( String alarmMessage ) If you called yourAlarm.setAlarm( 1000, Capacity reached ), you'd set the alarm message to trigger at 1000, printing the message Capacity reached. yourAlarm.setAlarm( Oops, all full ) might then be used when to change the warning to be issued when the AlarmedCounting reaches capacity. Overloading method names is the choice of the interface builder. The interface user simply makes use of the interface as it is given. 4.3.3 Interfaces are Types: Behavior Promises Now that we have these interfaces, what good do they do? Interfaces are kinds of Things: they are Java types. In Java, every interface name is automatically a type name. That is, when you are declaring a (label) name, you can declare it suitable for labeling things that implement a specific interface. In the next chapter, we will see how to declare Java classes and how to indicate what interface(s) the class implements. So, for example, the declared type of myCounting, above, was Counting: Counting myCounting; In this example, myCounting is declared to be of type Counting, i.e., something that satisfies the Counting contract (interface) that we declared in the preceding sections. For example, we might have an interface called Game that includes a getScoreCounter() method that returns a Counting: interface Game { abstract Counting getScoreCounter(); // maybe some other method signatures.... } If theWorldCupFinal is a Game, then we might say Counting myCounting = theWorldCupFinal.getScoreCounter(); In this case, we don't know anything more about the type of myCounting ; we just know that it is a Counting. Often, as users of other people's code, interfaces are the only types we need to know about. 4.3 Interface Declaration 4~15 IPIJ || Lynn Andrea Stein 4.3.4 Interfaces are Not Implementations We have seen that an interface can be used as the type of an object. You can use names associated with that type to label the object. You can pass objects satisfying that interface to methods whose parameter types are that interface type, and you can return objects satisfying that interface from a method whose return type is that interface. The Counting in the previous paragraph was an example of the power of interfaces. However, there are certain things that you cannot do with an interface. Of course, when we're manipulating that Counting object, we don't know anything about how it works inside. We don't know, for example, whether it has a touchdown part and a field goal part, or is represented in decimal or in binary, or is likely to keep going up while we're thinking about it (since players might keep scoring). To figure this out, we'd need to know more than just the interface -the contract -that it satisfies; we'd need to know how it is implemented. Interfaces are about contracts, promises. They don't, for example, tell you how to create objects that satisfy those promises. In the next several chapters, we'll learn about building implementations that satisfy these promises and about creating brand new objects that meet these specifications. To do that will require additional machinery beyond the contract/promise of an interface. 4~16 Specifying Behavior: Interfaces Chapter 4 IPIJ || Lynn Andrea Stein Style Sidebar Interface Documentation An interface should be properly documented, typically using a multi-line or javadoc comment immediately preceding its declaration. Documentation for an interface should include the following information: What kind of thing does this interface represent? Why would you want to use an object of this kind? What could it do for you? What could you do with it? What kinds of assumptions or conditions does this kind of object need to do its job? Are there any special objects that it might need to have around or to work with? What services does this kind of object provide, and how do you use them? These questions are typically answered by the individual methods, but a brief overview of what methods the interface provides is always useful. It is may also be useful for the interface to document which method(s) to use when, especially when multiple similar methods exist. The interface's documentation should make it easy for a potential user to find the method(s) s/he wants. It should also make it possible for someone seeking to implement this interface to determine whether s/he has met the intent as well as the formal specification of the interface. If I am building a stopwatch, do I want to subscribe to the Clock interface? Remember that an interface declaration is largely about what, not how. It specifies contracts and promises, not mechanism. Java provides additional support for some of these items in its javadoc utilities. See the appendix on javadoc for details.

Read the paper · More papers on PaperTik