Let’s recap where we are in the course. We’ve looked at three broad topics: Java classes and interfaces, data types, and data structures. How do these relate to one another? First, let’s summarizes these concepts individually:
An abstract datatype (ADT) specifies a type name, set of required operations (with type signatures), and axioms related the behavior of the operations.
A data structure specifies a shape of data and optional contraints (called invariants) on the data within that shape. The invariants are usually defined to guarantee some particular behavior characteristic, such as efficient execution, efficient space usage, security, etc. Many different data structures can implement the same datatype.
Java interfaces capture required ADT operations and their signatures (but not the axioms).
Java classes capture shapes of data (tree, list, etc).
Java methods maintain invariants and are responsible for providing any resource guarantees that those invariants provide.
When you need a new type name on a field so that it can take different classes as values (the mixed-data scenario). In this case, the mixed-data is really an ADT, just one that you’ve custom created for your application. We did this for animals, sports scores, and sports contestants.
When you’re told to implement an existing ADT. We did this for sets and priority queues.
We’ve seen one justification for abstract classes: when you want to share replicated code between existing classes. In particular, we don’t use an abstract class just to get shared type name. That’s the job of an interface.
Overall, we’ve been exploring two different aspects of system design: specification and implementation. In specification, we state requirements (what to do), but not implementation details (how to do it). Implementations provide concrete data and methods that satisfy specifications. Usually, there are many possible implementations for the same specification (for example, Lists, BSTs, and AVL trees all implement Sets). Sometimes, the same implementation satisfies multiple implementations (for example, Lists implement either Sets of Priority Queues). As you try to keep the course concepts straight, it might help to recall which aspect of system design each one supports:
ADT Data structure
Java interface Java classes
In 1101, you focused on a replicable design recipe for implementing data structures without invariants. In 2102, we’ve introduced the notion of specification and added invariants to data structures. We’ve also switched over to Java, so you can learn how these key aspects are realized in a particular (and popular) programming language. There’s more to come in the course on how to work with these concepts in Java. But the design recipe you learned in 1101/2 has remained intact.
We have, however, extended our treatment of testing. Previously, test cases exercised purpose statements against all the variants of input data. Now, test cases also have to exercise axioms (specification) and invariants (implementation). Some tests check that operators satisfy ADT axioms. Others check that implementations satisfy data structure invariants. If you are writing test cases for a data structure that implements an ADT, make sure you have tests for both invariants and axioms, as well as for the method’s purpose.