Liskov 6

advertisement
Iteration Abstraction
SWE 619 - Software Construction
Spring 2013
Common Collections

List (Interface)

AbstractList


Set (Interface)

AbstractSet


AbstractMap


HashSet, TreeSet
Map (Interface)


ArrayList, Linked List, Vector
HashMap, TreeMap
Arrays
Stack -subtype of Vector (Anomaly?)
2
Visiting each element of a
collection



Scenario: A common container has
several objects stored
Task: To visit each element in the
container
HOW?
3
Approaches

IntSet choose() method?



Return the collection?


Remove – choose combination
What is the problem here?
Why is this bad?
Return a clone?

Is this better?
4
Approaches

Custom built method?




Close, but not it
Problem? Not general
We want uniformity
Iteration Abstraction


Client code is simplified, using is easy
Implementation may be complex, but
standard
5
Iterator Interface
public Interface Iterator {
public boolean hasNext();
public Object next() throws NoSuchElementException;
public void remove() throws IllegalStateException;
}


Liskov has only first hasNext() and next()
To satisfy the compiler, you need to
override/implement remove() too
6
Specification
public boolean hasNext() ;
// Effects: Returns true if there are more elements to
yield else returns false
public Object next();
// Modifies: this
// Effects: If there are more results to yield, returns the
next result and modifies the state of this to record
the yield. Otherwise, throws NoSuchElementEx.
7
Definitions
An iterator is a procedure that returns a generator. A data
abstraction can have one or more iterator methods,
and there can also be standalone iterators.
A generator is an object that produces the elements used
in the iteration. The generator’s type is a subtype of
Iterator.
The specification of an iterator defines the behavior of
the generator; a generator has no specification of its
own. The iterator specification often includes a
requires clause at the end constraining the code that
uses the generator.
8
Examples: Poly and IntSet
public Iterator terms()
// Effects: Returns a generator that will produce exponents
// of nonzero terms of this (as Integers) up to the degree,
// in order of increasing exponent
public Iterator elements()
// Effects: Returns a generator that will produce all the elements
// of this (as Integers) each exactly once, in arbitrary order
// Requires: this must not be modified while the
// generator is in use
9
Example: Poly
Poly p … // p = 2 + 3 x2+ 4 x5
Iterator itr = p.iterator(); // Usual
Iterator itr = p.terms(); // Liskov’s itr = [0,2,5]
itr.hasNext()
// return true, itr = [0,2,5]
itr.next()
// return 0, itr = [2,5]
itr.next()
// return 2, itr = [5]
itr.hasNext()
// return true, itr = [5]
itr.next()
// return 5, itr = []
itr.hasNext()
// return false, itr = []
itr.next()
// return NSEE, itr = []
10
Abstraction Function


It’s the current list of things that you
are going to send back
Very close to a Stack




top = next() element
remove() adds complexity
If multiple interfaces, iterator may not
know about removed items!
Only mutable data types are affected
11
Af(c) for Poly Iterator
Poly p … // p = 2 + 3 x2+ 4 x5
AF(itr.hasNext()) =
AF(itr.next())
=
AF(itr.next())
=
AF(itr.hasNext()) =
AF(itr.next())
=
AF(itr.hasNext()) =
AF(itr.next())
=
[0,2,5]
[2,5]
[5]
[5]
[]
[]
[]
//true
//0
//2
//true
//5
//false
//NSEE
12
Implementation (Fig 6.8)
public class Poly{
// Rep …
public Iterator terms() {return new PolyGen(this);}
// inner class
private static class PolyGen implements Iterator {
private Poly p;
// the Poly being iterated
private int n;
// the next term to consider
PolyGen (Poly it){
//Requires: it !=null
p = it;
if(p.trms[0] == 0) n=1; else n= 0;
}
13
Implementation (contd.)
public boolean hasNext() {return n<= p.deg;}
public Object next () throws NSEE{
for(int e = n; e <= p.deg; e++) {
if (p.trms[e] != 0) {
n= e+1;
return new Integer(e);
}
}
throw new NSEE(“Poly.terms”);
} // end PolyGen
}
14
Inner Class




private class
visibility only inside the class where
defined
no outside code can see/instantiate it
if it has public methods && an instance
available, outside code can call it
15
State for iterator


How to figure out the state?
Same way as AF(c) for Data Abstraction

Ask yourself: What do I need to send back
to the client?

Example Rep state: [2,0,3,0,0,4]

What if PolyGen was immutable?
16
Another example: PrimesGen
private static class PrimesGen implements Iterator{
private Vector ps;
// primes yielded
private int p;
// next candidate to try
PrimesGen () { p =2 ; ps = new Vector();} //constructor
public boolean hasNext() {return true;}
// always true
public Object next() throws NSEE {
if (p==2) {p=3; return 2;}
for (int n=p; true; n = n+2){
… //Prime number generation
}
}
}// end of PrimesGen
17
Abstract State for PrimesGen?
Iterator itr = num.allPrimes();
AF(c) = [2,3,5,7,11,13,17,19, …]
No end? Can we figure out the length of the tail?
 What does hasNext() have to do in this case?
[2,3,5,7,9,…]
Integer x = (Integer) itr.next();
[3,5,7,9,11,..]
Integer y = (Integer) itr.next();
[5,7,9,11,13,17,…]
.
.

18
Exercises





What if there is an upper bound on the
prime numbers?
Suppose primes <100.
What will be AF(c) be like?
What will hasNext() implementation do?
How will implementation of PrimesGen
change?
19
Another Exercise
public Interface TwoWayIterator {
Object next ();
Object previous ();
boolean hasNext();
boolean hasPrevious();


Suppose we want to go back AND forward
What does the abstraction function look like?



Still a stack?
What other state information is needed?
How to implement this for Poly?
20
What about supporting
remove()?

The contract for remove():
Removes from the underlying collection the last element returned
by the iterator (optional operation). This method can be called
only once per call to next. The behavior of an iterator is
unspecified if the underlying collection is modified while the
iteration is in progress in any way other than by calling this
method.


This is complex!
What is the new abstract state?
21
Iterable vs. Iterator

Only one method required:


public Iterator<T> iterator();
Allows very nice code:
// Note: that Collection implements Iterable
// Side note: String does NOT implement Iterable
Set<String> mySet = new HashSet<String>();
// populate mySet with various Strings
for (String s : mySet) { // auto invocation of iterator(), next()
// do something with s
}
22
Related documents
Download