Types, again |
The type of an object is specified by he collection of operations/methods that can be used from outside a class to interact with an object of the class. In Java and other object-oriented languages, what we have called the type of an object is called the interface to the class. This explains why the topics "Interfaces" and "User Interfaces" have related names. "User Interfaces" are the mechanisms through which users can interact with the state of an entire program. "Interfaces" are the mechanisms through which one component (object) within a program can interact with another.
The type of objects for a Grace class can be concisely described by listing all of its methods and describing their parameters. That is why we ask you to include such information in your designs.
We illustrate with the type of the box class in this week's homework.
type Box = // move box to new randomly chosen position moveBox-> Done // change width of the box width:=(boxSize:Number)-> Done // left edge of box left->Number // right edge of box right->Number // are right and left edges of ball within left and right // walls of the box containsObject(ball:Graphic2D)->Boolean
Here is another - the type of Tshirt objects
type Laundry = // move the item by specified offsets moveBy(dx:Number, dy:Number) -> Done // move the item to a specified position moveTo(point:Point) -> Done // check to see if the item contains a specified location contains(point:Point) -> Boolean color -> Color color:=(newColor:Color) -> Done reset -> Done sendToFront -> Done removeFromCanvas -> Done
With this interface included in our program, we can now construct a more advanced version of the laundry sorter.
We hope that you noticed that, thanks to the use of a type definition, we had to change very little when we converted our initial laundry program (where the laundry items were just FilledRects) into our current, fancy Tshirt version. Basically, the only change required was that the declaration:
item: Graphic2D
had to be replaced by a declaration of the form:
item: Laundry
and to change the constructor used.
The code that manipulated the laundry (i.e. onMouseDrag, etc.) remained unchanged. types let us write even more flexible code.
Suppose we have two classes of laundry defined. Tshirts (as before) and something else like Pants. If they both contain all the methods listed in our Laundry interface, we can explicitly tell Grace this in the headers of the class declarations:
class tshirt.at(...) -> Laundry ...
So long as we restrict ourselves to the methods defined by the Laundry type, it doesn't matter what type of laundry we come up with in the future (maybe we want to add Wool Socks for the winter). We can continue to use any program that manipulates objects via the Laundry type without changing it!
This makes a lot of sense. In the specification of the type Laundry, we did not include a constructor. That is because in order to construct an object, we need to know the details of how its state will be represented. The whole point of an interface, however, is to focus on the interface through which the state can be manipulated while ignoring the details of how the state is represented.
On the other hand, given that Grace knows that "item" will only be associated with things that implement the Laundry interface, it will let us write commands like:
item.moveTo(...);
Types, again |