This would lead us to a Catcher interface that extends the Fielder interface. Similarly, all
pitchers are fielders, but there is a dizzying array of statistics that we would want to track for
pitchers that don't apply to other fielders. Whether we want a Pitcher interface to extend the
basic Fielder interface or have a separate interface just for pitching statistics (and then have
the Pitcher class implement both of those interfaces) is a separate design decision.
The good part about Java's type system is that the separation between interface and class al-
lows us to do our semantic design (which has to do with interfaces) separately from our class
design (which has to do with implementations). Such a separation allows us to think about the
meaning without thinking about how we are going to implement that meaning, simplifying
Inside and Out
This leads us back to why it is important to declare arguments and return values using inter-
faces rather than classes. When you pass in an object to a method, all that the code in the
method should care about is the set of operations that can be performed on that object. How
the method is implemented should never be assumed by the method that receives the object,
because that can always change. In fact, all that the method should care about are the relations
between the various methods for the objects that are passed in. And this is what is defined by
the interface, not the class.
Similarly, all the recipient of a return value object should have to know about that object is
the set of operations that can be performed on it. There is no need to know how those opera-
tions are implemented or the actual state that is stored in the object. There may even be other
operations on the object that are not relevant to the receiver. All that needs to be known is the
interface of the object returned.
This gives us a guideline for good use of the Java type system. Interfaces are used to define
sets of interrelated operations that, taken together, form a unit of meaning in an application.
An interface tells us a minimum of what an object does, and is the way to define arguments
and return values for a method. Methods require as arguments objects that do at least what the
interfaces specify, and methods return an object that does at least what the interface specified
as the return value requires.
Classes, on the other hand, allow us to define a set of related data, and to associate that data
with the code that is used to manipulate that data. Classes really allow us to do the basic asso-
ciation of object-oriented programming, which is to associate some collection of data with the
code that is used to manipulate that data. The association of inheritance allows us to extend