Comp 302: Software Engineering Data Abstractions.

28
Comp 302: Software Engineering Data Abstractions

Transcript of Comp 302: Software Engineering Data Abstractions.

Page 1: Comp 302: Software Engineering Data Abstractions.

Comp 302: Software Engineering

Data Abstractions

Page 2: Comp 302: Software Engineering Data Abstractions.

Data Abstraction

data abstraction = <objects,operations>

Why data abstractions?

When the implementation of the abstraction changes, programs that use it don’t have to change.

Only access the object through methods it provides Can avoid making implementation decisions too early

Avoid inefficiencies and massive re-implementation Can first define the abstract type with its operations

Can then work on using modules Make implementation decisions later

Page 3: Comp 302: Software Engineering Data Abstractions.

Outline

How to specify data abstractions? How to implement data abstractions?

Page 4: Comp 302: Software Engineering Data Abstractions.

Specifications for Data Abstractions

visibility class dname {// OVERVİEW: A brief description of the

// behaviour of the type’s objects goes here//constructors//specs for constructors go here

//methods//specs for methods go here

}

Page 5: Comp 302: Software Engineering Data Abstractions.

Specification of IntSet (code filled in later)public class IntSet {

//OVERVİEW: IntSets are mutable, unbounded sets of integers//A typical IntSet is {x1,...,xn}.

//constructorspublic IntSet ( )

//EFFECTS: Initialize this to be empty. (no need for MODIFIES clause)

//methodspublic void insert (int x)

// MODIFIES: this// EFFECTS: Adds x to the element of this, // i.e., this_post = this + {x}

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 cordinality of this

public int choose () throws EmptyException// EFFECTS: If this is empty, throws EmptyException

// else returns an arbitrary element of this.}

mutators

observers

Page 6: Comp 302: Software Engineering Data Abstractions.

Mutability States of immutable objects never change

They are created and they stay that way until destroyed Example: Strings Huh? What about

String myFirstName = “Serdar”;String myLastName = “Tasiran”;String myFullName = myFirstName + “ “ + myLastName;

A new String object is created. The String with “Serdar” in it is never changed.

Mutable objects: Example: Arrays. a[i] = 5; If a mutable object is shared, a modification of one modifies the other.

Page 7: Comp 302: Software Engineering Data Abstractions.

public class Poly {//OVERVIEW: Polys are immutable polynomials with integer coefficients.//A typical Poly is c0 + c1x + c2x2 + ... + cnxn

//constructorspublic Poly ()

//EFFECTS: Initializes this to be zero polynomial

public Poly (int c, int n) throws NegativeExponentException// EFFECTS: If n<0 throws NegativeExponentException else initalizes this

// to be the Poly cxn.

//methodspublic int degree ()

// EFFECTS: Returns the degree of this, i.e., the largest exponent with a // non-zero coefficient. Returns 0 if this is zero Poly.

public int coeff (int d)// EFFECTS: Returns the coefficient of the term of this whose exponent is

// d.

public Poly add (Poly q) throws NullPointerException// EFFECTS: If q is null throws NullPointerException else returns the Poly

// this +q.

public Poly mul (Poly q) throws NullPointerException// EFFECTS: If q is null throws NullPointerException else returns the Poly

// *q.

public Poly sub (Poly q) Throws NullPointerException// EFFECTS: If q is null throws NullPointerException else returns the Poly

// this –q.

public Poly minus ()//EFFECTS: Returns the Poly – this.

}

Page 8: Comp 302: Software Engineering Data Abstractions.

Design Issues: Mutability When to make a data type mutable, when not to. Type should be immutable when its elements would naturally

have unchanging values We’ll talk more on this later, but in general, when modeling real-

world objects, types should be mutable Mostly mathematical or other symbolic objects are not mutable.

This allows more sharing of subparts

Immutable: Safe, but may be inefficient Create and discard many intermediate objects before

completing computation Lots of garbage collection

Mutable: Less garbage collection, less safe.

Page 9: Comp 302: Software Engineering Data Abstractions.

Using Data Abstractionspublic static Poly diff (Poly p) throws NullPointerExcepyion {

//EFFECTS: If p is null throws NullPointerException //else returns the Poly obtained by differentiating

p.Poly q = new Poly ();for (int i = 1; i <= p.degree(); i++)

q = q.add(new Poly(p.coeff(i)*i, i - 1));return q;

}

public static IntSet getElements (int[] a)throws NullPointerException {

//EFFECTS: If a is null throws NullPointerException //else returns a set containing an entry for each //distinct element of a.IntSet s = new IntSet();for (int i = 0; ,< a.length; i++) s.insert(a[i]);return s;

}

Page 10: Comp 302: Software Engineering Data Abstractions.

Implementing Data Abstractions Must select a representation (rep).

Examples: A Vector (from java.util) of Integer objects is a possible

rep for IntSet Reps must

Support all operations in a simple way Provide efficient implementations

Searching an entry should not require looking at all entries, ideally.

Page 11: Comp 302: Software Engineering Data Abstractions.

A Rep for IntSet

Should we allow each element to occur more than once or not If we do, insertion is simple: Just add it at the end

of the Vector But remove and isIn take a long time

isIn is likely to be called a lot Forbid duplicates in Vector

Page 12: Comp 302: Software Engineering Data Abstractions.

Implementing Data Abstractions A representation typically has several components

Correspond to (non-static) fields in the class definitions These are also called instance variables

There is a separate set of them for each object

Use static fields to store information that applies to all objects of that class Example: The number of instances created.

Instance variables must not be visible to users, other classes Make them private Provide methods to access and modify them

Page 13: Comp 302: Software Engineering Data Abstractions.

public class IntSet {//OVERVIEW: IntSets are unbounded, mutable sets of integers.

private Vector els; // the rep

//constructors

public IntSet () {//EFFECTS: Initializes this to be emptyels = new Vector(); }

//methods

public void insert (int x) {//MODIFIES: this//EFFECTS: Adds x to the elements of this.Integer y = new Integer(x);if (getIndex(y) < 0) els.add(y); }

public void remove (int x) {//MODIFIES: this//EFFECTS: Removes x from this.int i = getIndex(new Integer(x));if (i < 0) return;els.set(i, els.lastElement());els.remove(els.size() - 1); }

public boolean isIn (int x) {//EFFECTS: Returns true if x is in this else returns false.return getIndex(new Integer(x)) }

(Continued)

Page 14: Comp 302: Software Engineering Data Abstractions.

private int getIndex (Integer x) {//EFFECTS: If x is in this returns index

where //x appears else returns -1.for (int i = 0; i < els.size(); i++)

if (x.equals(els.get(i))) return i;return -1; }

public int size () {//EFFECTS: Returns the cardinality of this.return els.size(); }

public int choose () throws EmptyException {//EFFECTS: If this is empty throws EmptyException

else //returns an arbitrary element of this.if(els.size() == 0) throw new

EmptyException(“IntSet.choose”);return els.lastElement(); }

}

Page 15: Comp 302: Software Engineering Data Abstractions.

public class Poly {

//OVERVIEW: ...private int[] trms;private int deg;

//constructorspublic Poly () {

//EFFECTS: Initilizes this to be the zero polynomial.

trms = new int[1]; deg = 0; }

public Poly (int c, int n) throws NegativeExponentException {

//EFFECTS: If n < 0 throws NegativeExponentException // else initializes this to be the Poly cxn.

if (n < 0) throw new NegativeExponentException(“Poly(int,int) constructor”); if (c == 0) { trms = new int[n+1]; deg = n; } trms = new int [n+1]; for (int i = 0; i < n; i++) trms[i] = 0; trms[n] = c; deg = n; }

Page 16: Comp 302: Software Engineering Data Abstractions.

private Poly (int n) { trms = new int[n+1]; deg = n; }//methods

public int degree () { // EFFECTS: Returns the degree of this, i.e.,

// the largest exponent with a non-zero coefficient. // Returns 0 if this is the zero Poly.

return deg; }

public int coeff (int d) { // EFFETCS: Returns the coefficient of the

// term of this whose exponent is d.

if (d < 0 || d > deg) return 0; elsereturn trms[d]; }

public Poly sub (Poly q) throws NullPointerException { // EFFECTS: If q is null throws // NullPointerException else returns add (q.minus()); }

public Poly minus () { //EFFECTS: Returns the Poly –this.

Poly r = new Poly(deg); for (int i = 0; i < deg; i++) r.trms[i] = - trms[i]; return r; }

Page 17: Comp 302: Software Engineering Data Abstractions.

public Poly add (Poly q) throws NullPointerException {

// EFFECTS: If q is null throws NullPointerException // else returns this +q.

Poly la, sm;

if (deg < q.deg) {la = this; sm = q;} else {la = q; sm = this;}

int newdeg = la.deg; //new degree is the larger degree

if (deg == q.deg) //unless there are trailing zeros

for (int k = deg; k > 0; k--) if (trms[k] + q.trms[k] != 0) break; else newdeg--;

Poly r = new Poly(newdeg); //get a new Polyint i;for (i = 0; i <= sm.deg && i <=newdeg; i++)

r.trms[i] = sm.trms[i] + la.trms[i];for (int j = i; j <= newdeg; j++) r.trms[j] = la.trms[j];return r;

}

Page 18: Comp 302: Software Engineering Data Abstractions.

public Poly mul (Poly q) throws NullPointerException {// EFFECTS: If q is null throws NullPointerException

// else returns the Poly this *q.

if ((q.deg == 0 && q.trms[0] == 0) || (deg == 0 && trms[0] == 0))

return new Poly();

Poly r = new Poly(deg+q.deg);r.trms[deg+q.deg] = 0; //prepare to compute coeffs

for (int i = 0; i <= deg; i++) for (int j = 0; j <= q.deg; j++)

r.trms[i+j] = r.trms[i+j] + trms[i] * q.trms[j];return r;

}

Page 19: Comp 302: Software Engineering Data Abstractions.

Implementation Decisions Suppose our array is sparse

2x1001 – x2 + 3x – 1 We would have an array with 999 zeros

Very inefficient

Alternative Store only non-zero coefficients and their associated exponents private Vector coeffs;

private Vector exps; Problem: Must keep the two vectors lined up. Better to have one Vector, with “records” representing (coeff, exp) pairs.

class Pair {//OVERVIEW: A record typeint coeff;int exp;Pair(int c, int n) { coeff = c; exp = n; }

} // No spec needed: Package accessible fields.

Page 20: Comp 302: Software Engineering Data Abstractions.

RecordsInstead of

public int coeff (int x) {for (int i = 0; i < exps.size(); i++)

if (((Integer) exps.get(i)).intValue() == x)return ((Integer)

coeff.get(i)).intValue();return 0; }

We now have

private Vector trms; // the terms with non zero coefficientspublic int coeff (int x) {

for (int i = 0; i < trms.size(); i++) {Pair p = (Pair) trms.get(i);if (p.exp == x) return p.coeff; }

return 0; }

Page 21: Comp 302: Software Engineering Data Abstractions.

Methods Inherited from Object All classes are subclasses of Object They

either provide implementations for all of Object’s methods equals, clone, toString, …

or inherit Object’s version of these methods

Two objects should be equals if they are behaviorally equivalent, i.e., cannot distinguish them using the object’s own methods

Distinct mutable objects are always distinguishableIntSet s = new IntSet();IntSet t = new IntSet();if (s.equals(t)) ...; else ...

Page 22: Comp 302: Software Engineering Data Abstractions.

cloneing Makes a copy of its object

The copy should have the same state

Object defines a default implementation Creates a new object of the same type, copies each instance field

Often not correct for the object we’re dealing with For IntSet, the two copies would share the els Vector. If one is modified, the other will be also Must generate independent copy

For immutable objects, it is OK to share fields Fields never get changed

In general, immutable objects should inherit from Object, mutable ones should provide their own implementation.

Usage: visibility class Classname implements Cloneable { }

Page 23: Comp 302: Software Engineering Data Abstractions.

public class Poly implements Cloneable {//as given before, plus

public boolean equals (Poly q) {if (q == null || deg != q.trms.length) return

false;for (int i = 0; i <= deg; i++)

if (trms[i] != q.trms[i]) return false;return true; }

public boolean equals (Object z) {if(!(z instanceof Poly)) return false;return equals((Poly) z); }

}

public class IntSet {//as given before, plusprivate IntSet (Vector v) { els = v; }

public Object clone () {return new IntSet((Vector) els.clone()); }

}

If you invoke clone() on an object that doesn’t implement Cloneable, the clone() method inherited from Object throws the CloneNotSupportedException.

Page 24: Comp 302: Software Engineering Data Abstractions.

Typecasting Clones

IntSet t = (IntSet) s.clone();

Page 25: Comp 302: Software Engineering Data Abstractions.

The toString method toString() returns a String that represents the state of the object. The default method provided by Object prints the type name and hash code.

Not very useful Must provide our own toString() implementation Examples:

IntSet: {1, 7, 3}Poly: 2 + 3x + 5x^2

IntSet implementation:

public String toString () {if (els.size() == 0) return “IntSet:{}”;String s = “IntSet: {“ els.elementAt(0).toString();for (int i = 1; i < els.size(); i++)

s = s + “ , “ + els.elementAt(i).toString();return s + “}”; }

Page 26: Comp 302: Software Engineering Data Abstractions.

Unknowingly Exposing the Rep: BAD!!!public Vector allEls()

//EFFECTS: Returns a vector containing the //elements of this, each exactly once, in //arbitrary order{

return els; }

public IntSet (Vector elms) throws NullPointerException // EFFECTS: If elms is null throws // NullPointerException else initializes this to // contain as elements all the ints in elms.

{if (elms == null)

throw new NullPointerException(“IntSet 1 argument constructor”);

els = elms;}

Page 27: Comp 302: Software Engineering Data Abstractions.

Operation Categories Creators:

Create an object from scratch A constructor with no arguments

Producers: Take object(s) of your own type Generate a new one Examples: Constructors with arguments of same type, mul method

of Poly (returns Poly) Mutators:

Modifies objects of its type : insert, delete for IntSet

Observers: Reports something about its current state

Page 28: Comp 302: Software Engineering Data Abstractions.

Adequacy Provide enough operations

Everything that the user of your class wants can be done Simply: a few method calls at most Efficiently: doesn’t take a long time to complete

Type must be fully populated Must be possible to obtain all possible abstract states using

methods Example: Must be able to get any IntSet

But don’t provide too many operations Complicated to understand Difficult to maintain

If rep changes, you have to fix a lot of methods