cs205: engineering software? |
(none) 20 September 2010 |
cs205 Data Abstraction Notes
(Friday 8 September - Monday 11 September)
What are the advantages and disadvantages of using abstract data types?
What are the minimal operations a (useful) data abstraction must provide?
Is it reasonable for a datatype to have no creators?
Is it reasonable for a datatype to have no observers?
public class SetWhat missing operations are needed for an adequate Set datatype?{ OVERVIEW: A Set is a mutable, unbounded set of objects of type T. A typical Set is {x_1, ..., x_n }. public Set() EFFECTS: Initializes this to an empty set: { }. public boolean add(T el) MODIFIES: this EFFECTS: Adds el to the elements of this: thispost = thispre U { el } Returns true iff el was not an element of thispre. public boolean contains(T el) EFFECTS: public void union(Set<T> t)
Is it necessary to provide union?
The Abstraction Function maps a concrete state to an abstract state:
AF: C → AIt is a function from concrete representation to the abstract notation introduced in overview specification.
// AF (c) = { AFT (c.els[i]) | 0 <= i < c.els.size () }Representation Invariant
The Representation Invariant expresses properties all legitimate objects of the ADT must satisfy. It is a function from concrete representation to boolean:
I: C → boolean
To check correctness we assume all objects passed in to a procedure satisfy the invariant and prove all objects satisfy the invariant before leaving the implementation code.
public class Set<T> { // OVERVIEW: A Set is a mutable, unbounded set of objects of type T. // A typical Set is {x_1, ..., x_n }. // Representation: private Vector<T> rep; // RepInvariant (c) = c.rep contains no duplicates && c.rep != null // && all elements of c.rep are of non-nullIf we instead used RepInvariant (c) = true which operations would be easier to implement correctly? Which would be harder?
Where can an implementer of a datatype assume the rep invariant is true?
Where must an implementer of a datatype ensure the rep invariant is true?
public class Graph { // OVERVIEW: // A Graph is a mutable type that represents an undirected // graph. It consists of nodes that are named by Strings, // and edges that connect a pair of nodes. // A typical Graph is: < Nodes, Edges > // where // Nodes = { n1, n2, , nm } // and // Edges = { {a_1, b_1}, ..., {a_n, b_n} } // (note that the elements of Edges are unordered sets) // Creator public Graph () // EFFECTS: Initializes this to a graph // with no nodes or edges: < {}, {} >. // Mutators public void addNode (String name) throws DuplicateException // MODIFIES: this // EFFECTS: If name is in Nodes, throws DuplicateException. // Otherwise, adds a node named name to this: // this_post = < Nodes_pre U { name }, Edges_pre > public void addEdge (String fnode, String tnode) throws NoNodeException, DuplicateException // MODIFIES: this // EFFECTS: If s and t are not names of nodes in // this, throws NoNodeException. If there is already an edge // between s and t, throws DuplicateEdgeException. // Otherwise, adds an edge between s and t to this: // thispost = < Nodespre, Edgespre U {fnode, tnode} > // Observers public boolean hasNode (String node) // EFFECTS: Returns true iff node is a node in this. SetgetNeighbors (String node) // REQUIRES: node is a node in this // EFFECTS: Returns the set consisting of all nodes in this // that are directly connected to node: // { n | {node, n} is in this.edges } }