David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 5: Implementing Data Abstractions
11 September 2003CS 201J Fall Menu Data Abstraction Specifying Abstract Data Types Implementing Abstract Data Types
11 September 2003CS 201J Fall Abstract Data Types Separate what you can do with data from how it is represented Client interacts with data through provided operations according to their specifications Implementation chooses how to represent data and implement its operations
11 September 2003CS 201J Fall Data Abstraction in Java A class defines a new data type Use private instance variables to hide the choice of representation –private declarations are only visible inside the class
11 September 2003CS 201J Fall Up and Down Abstract Type Concrete Representation class implementation clients down up The representation of an abstract data type is visible only in the class implementation. Clients manipulate an abstract data type by calling its operations (methods and constructors)
11 September 2003CS 201J Fall StringSet Abstract Type Concrete Representation class implementation clients down up { “test”, “okay” } private Vector res; s.isIn () public boolean isIn () { … }
11 September 2003CS 201J Fall Advantages/Disadvantages -More code to write and maintain -Run-time overhead (time to call method) +Client doesn’t need to know about representation +Localize impact of changes
11 September 2003CS 201J Fall StringSet Example StringSet abstract data type: represent a set of strings Support mathematical set operations: insert, isIn, size Create an empty set
11 September 2003CS 201J Fall Specifying Abstract Data Types Overview: what does the type represent –Mutability/Immutability A StringSet is a mutable set of Strings. –Abstract Notation A typical StringSet is { x 1, …, x n }. Operations: specifications for constructors and methods clients use –Describe in terms of abstract notation introduced in overview.
11 September 2003CS 201J Fall StringSet Specification public class StringSet // OVERVIEW: StringSets are unbounded, mutable sets of // Strings. A typical StringSet is { x1,..., xn } public StringSet () // EFFECTS: Initializes this to be empty: { } public void insert (String s) // MODIFIES: this // EFFECTS: Adds x to the elements of this: // this_post = this_pre U { s } public boolean isIn (String s) { // EFFECTS: Returns true iff s is an element of this. public int size () // EFFECTS: Returns the number of elements in this.
11 September 2003CS 201J Fall Components of Data Abstractions Ways to create objects of the data type –Creators: create new objects of the ADT from parameters of other types –Producers: create new objects of the ADT from parameters of the ADT type (and other types) Ways to observe properties: observers Ways to change properties: mutators
11 September 2003CS 201J Fall StringSet Operations Creators StringSet () Producers none Observers isIn, size Mutators insert public class StringSet // OVERVIEW: StringSets are unbounded, mutable sets of // Strings. A typical StringSet is { x1,..., xn } public StringSet () // EFFECTS: Initializes this to be empty: { } public void insert (String s) // MODIFIES: this // EFFECTS: Adds x to the elements of this: // this_post = this_pre U { s } public boolean isIn (String s) { // EFFECTS: Returns true iff s is an element of this. public int size () // EFFECTS: Returns the number of elements in this.
11 September 2003CS 201J Fall Using Abstract Data Types PS1, PS2 Client interacts with data type using the methods as described in the specification Client does not know the concrete representation
11 September 2003CS 201J Fall Implementing Abstract Data Types
11 September 2003CS 201J Fall Choosing a Representation Need a concrete data representation to store the state Think about how methods will be implemented –A good representation choice should: Enable easy implementations of all methods Allow performance-critical methods to be implemented efficiently
11 September 2003CS 201J Fall StringSet Representation Option 1: private String [] rep; –Recall Java arrays are bounded –Easy to implement most methods, hard to implement insert Option 2: private Vector rep; –Easy to implement all methods –Performance may be worse than for array
11 September 2003CS 201J Fall Implementing StringSet public class StringSet { // OVERVIEW: StringSets are unbounded, mutable sets of Strings. // A typical StringSet is {x1,..., xn} // Representation: private Vector rep; public StringSet () { // EFFECTS: Initializes this to be empty: { } rep = new Vector (); } public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } rep.add (s); } Could this implementation of insert be correct?
11 September 2003CS 201J Fall It depends… public int size () { // EFFECTS: Returns the number of elements in this. StringSet uniqueels = new StringSet (); for (int i = 0; i < rep.size (); i++) { String current = (String) rep.elementAt (i); if (uniqueels.isIn (current)) { ; } else { uniqueels.insert (current); } return uniqueels.rep.size (); }
11 September 2003CS 201J Fall Is it correct? public int size () { // EFFECTS: Returns the number of // elements in this. return rep.size (); } public void insert (String s) { if (!isIn (s)) rep.add (s); }
11 September 2003CS 201J Fall Reasoning About Data Abstractions How can we possibly implement data abstractions correctly if correctness of one method depends on how other methods are implemented? How can we possibly test a data abstraction implementation if there are complex interdependencies between methods?
11 September 2003CS 201J Fall What must we know to know size is correct? This implementation is correct only if we know the rep does not contain duplicates public int size () { // EFFECTS: Returns the number of // elements in this. return rep.size (); }
11 September 2003CS 201J Fall Rep Invariant The Representation Invariant expresses properties all legitimate objects of the ADT must satisfy I : C → boolean Function from concrete representation to boolean. Helps us reason about correctness of methods independently
11 September 2003CS 201J Fall Reasoning with Rep Invariants Prove all objects satisfy the invariant before leaving the implementation code Assume all objects passed in satisfy the invariant REQUIRES: Rep Invariant is true for this (and any other reachable ADT objects) EFFECTS: Rep Invariant is true for all new and modified ADT object on exit.
11 September 2003CS 201J Fall Rep Invariant for StringSet public class StringSet { // OVERVIEW: StringSets are unbounded, // mutable sets of Strings. // A typical StringSet is {x1,..., xn} // Representation: private Vector rep; // RepInvariant (c) = //c contains no duplicates //&& c != null
11 September 2003CS 201J Fall Implementing Insert? public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } rep.add (s); } Not a correct implementation: after it returns this might not satisfy the rep invariant!
11 September 2003CS 201J Fall Implementing Insert public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } } Possibly correct implementation: we need to know how to map rep to abstraction notation to know if this_post = this_pre U { s }
11 September 2003CS 201J Fall Tomorrow in Section Return PS2 Consider how to implement the Graph datatype specified in your notes Think about possible representations before tomorrow’s class