260 likes | 376 Views
Learn about abstract states, mutable vs. immutable objects, and operation specifications in software construction with practical examples.
E N D
Data Abstraction SWE 619 Software Construction Last Modified, Spring 2009 Paul Ammann
Data Abstraction • Abstract State (Client State) • Representation State (Internal State) • Methods • Constructors (create objects) • Producers (return immutable object) • Mutators (change state) • Observers (report about state)
Motivation • Why data abstraction? • Why hide implementation? • Client code breaks • Malicious or clueless clients don’t depend on/mess up the state • Maintain properties like rep invariant • Hence, encapsulation
IntSet and Poly • Poly 5+3x+8x3,4x+6x2 c0+c1x+… Immutable Students find this harder to implement but a better approach • IntSet {4,6} {}, {3,5,9}, {x1, …, xn} Mutable Students find this easy to implement
Specification of IntSet public class IntSet { //Overview: IntSets are mutable, unbounded sets of integers // A typical IntSet is {x1, …, xn} //constructors public IntSet() //Effects: Initializes this to be empty //methods public void Insert (int x) // Modifies: this // Effects: Adds x to this, i.e., this_post = this + {x}
Specification of IntSet (2) public void remove (int x) //Modifies: this //Effects: Removes x from this, i.e., this_post=this –{x} public boolean isIn (int x) //Effects: If x is in this, returns true, else returns false public int size () //Effects: Returns the cardinality of this public int choose () throws EmptyException // Effects: If this is empty, throws EmptyException else // returns an arbitrary element of this
Remember! • Don’t mention internal state in constructor or method specifications • Always override toString() (don’t show the rep) • Client should not see in-between state, all operations atomic • this_post after execution of procedure
Set Notation – figure 5.3 A set is denoted {x1, … xn} Set union: t = s1 + s2 Set difference: t = s1 – s2 Set intersection: t = s1 & s2 Cardinality |s| denotes the size of set s Set membership: x in true if x element of set s Set former: t = { x | p(x)} is the set of all x such that p(x) is true These few notions are extremely powerful!
Specification of Poly public class Poly { // Overview: Polys are immutable polynomials with integer co- // -efficients. A typical Poly is c0+c1x+ … //constructors public Poly() // Effects: Initializes this to be the zero polynomial public Poly (int c, int n) throws NegativeExponentException // Effects: If n<0 throws NegativeExponentException // else initializes this to be the Poly cxn
Specification of Poly (2) //methods public int degree () //Effects: Returns the degree of this (the largest exponent // with non zero coeff. Returns 0 if this is the zero Poly public int coeff (int d) //Effects: Returns the coeff of the term of this with exp. d (what if d > degree? what if d < 0?) public Poly add (Poly q) throws NullPointerException //Effects: If q is null throws NPE else // returns the Poly this + q public Poly mul (Poly q) throws NPE //Effects: if q is null throws NPE, else returns this * q
Poly in detail • 5+3x+8x3 can’t build with the constructor • Only zero or monomial • NegativeExponentException • No modifies clause: Immutable • No mutators • How does it support add, remove, multiply etc.?
Collections – A Slight Diversion D U P L I C A T E S N Y N Y One collection is often implemented with another.
Implementation (IntSet) • Rep: Vector Abstract state: Set • Design decision (els never null) • Use of special value in getIndex, justified? • Design decision, duplicates in insert • Why is remove as shown?
Implementation of IntSet (2) private Vector els; // the rep public void insert (int x) { //Modifies: this (NOT els!) //Effects: Adds x to the elements of this (NOT els!) Integer y = new Integer(x); if (getIndex(y) < 0) els.add(y); } private int getIndex(Integer x) { // Effects: If x is in this return index where x appears // else return -1 for (int i=0; i < els.size(); i++) if (x.equals(els.get(i))) return i; return -1; }
Implementation of IntSet (3) public void remove (int x) { //Modifies: this //Effects: Remove x from this int i = getIndex(new Integer(x)); if (i < 0) return; els.set(i, els.lastElement()); els.remove(els.size() - 1); } public int choose() { // Effects: If this empty throw EE else return arbitrary element of this if (els.size() == 0) throw new EE(“IntSet.choose”); return ((Integer) els.lastElement()).intValue(); }
Implementation of Poly (1) private int[] trms; private int deg; public Poly() { //Effects: Initializes this to be the zero polynomial trms = new int[1]; trms[0] = 0; deg = 0; } public Poly (int c, int n) throws IAE { //Effects if n < 0 throw IAE else initializes this to cx^n if (n < 0) throw new IAE(“Poly.constructor”); if (c ==0) { trms = new int[1]; trms[0] = 0; deg = 0; return} trms = new int[n+1]; deg = n; for (int i = 0; i < n; i++) trms[i] = 0; trms[n] = c; } private Poly (int n) { trms = new int[n+1] deg = n;}
Implementation of Poly (2) public int degree() { //Effects: Return degree of this, ie the largest exponent // with a nonzero coefficient. Returns 0 if this is the zero Poly return deg;} public coef (int d) { // Effects: Returns the coefficient of the term of this whose exp is d if (d < 0 || d > deg) return 0; else return trms[d];} // implementations of add, sub, minus, mul
Abstraction Function • Abstract state {x1, …, xn} • Representation state? Vector els = [y0, y1, …, yn] • Representation state is designer’s choice. • Clients don’t see rep (representation state), only see abstract state • Clients don’t care for rep, as long as it satisfies properties of abstract state • Implementer can change rep at any time!
Abstraction Function (IntSet) • Abstraction function is a mapping from representation state to abstract state • Abstraction function for IntSet: • AF(c) = c.els[i] | 0 i < c.els.size() } • If duplicates allowed, what should AF(c) be? • What if null is mapped to {}?
AF() AF() for IntSet Abstract State (IntSet s) s = {} s = {1, 2} s = {1} s = {1, 7} els = [null, 5] els = [1, 2] els = [] els = [2, 1] els = null els = [“cat”, “hat”] els = [7, 1, 7] Representation State (Vector els)
Rep Invariant • Rep Invariant is the expression of combined restrictions on representation • c.els != null • No duplicates in c.els • All entries in c.els are Integers • No null entries • English descriptions are fine! • These are DESIGN DECISIONS. • For example, we COULD allow duplicates...
Additional Methods • clone() wrong in Liskov; we will use Bloch • toString() Implementation of abstraction function • equals() non standard wrt Java - understand why • In terms of mutability– different for mutable and immutable types • Bias towards correctness • Three different things are required: • == // This checks if same object • equals() // for immutable only (same abstract state) • similar() // Mutable (same current abstract state) // Not implemented in Java
equals() • Involves three important criteria: reflexivity, symmetry, transitivity • Often difficult to implement • For abstract extensions of instantiable superclasses, impossible to implement! • Details later... • toString Should match with “typical object” • Trick: Do it backwards - implement toString() first and then write the abstraction function.
Mutable/Immutable Transform • Stack example in Bloch • Mutable • Transform to an immutable version • We should be fine with immutable stacks: Immutable Stack s = new Stack(); s = s.push(“cat”); s =s.push(“dog”); • How to tranform:
Mutator Producer Consider a mutator method in class C: public void m(T t) or public S m(T t) What do the corresponding immutable methods look like? public C m(T t) or public ??? m(T t) Second needs to be split into two methods: Example: pop() vs. pop(), top() in Stack