250 likes | 266 Views
Section 7 topics. Prelim review. Inner classes. Iterators. Prelim review, problem 1. C1. I1. C2. I2. C3. Prelim review, problem 1. C1 obj1. obj3 = obj2. obj2 = obj1. I1 i1. C2 obj2. i1 = obj3. obj3 = obj1. I2 i2. C3 obj3. i2 = obj1. Prelim review, problem 4.
E N D
Section 7 topics • Prelim review. • Inner classes. • Iterators.
Prelim review, problem 1 C1 I1 C2 I2 C3
Prelim review, problem 1 C1 obj1 obj3 = obj2 obj2 = obj1 I1 i1 C2 obj2 i1 = obj3 obj3 = obj1 I2 i2 C3 obj3 i2 = obj1
Prelim review, problem 4 • Reversing a list without allocating new objects. • Use iteration! • Keep track of the current object and the previous object.
Prelim review, problem 4 static public ListCell reverse(ListCell f) { ListCell current, previous; // check two base cases if (f == null) return null; if (f.getNext() == null) return f; // set the initial values of the // variables current = f.getNext(); previous = f; previous.setNext(null); while (current != null) { ListCell temp = current.getNext(); current.setNext(previous); previous = current; current = temp; } return previous; }
Prelim review,problem 6 • Interesting (?) question: find a general algorithm which given two lists decides whether there is a tree, which postorder traversal results in the first list, and preorder in the second one. • Even more interesting (??) question: Find one which is efficient.
Iterators • Abstract concept: Containers. • Instances: Arrays, trees, sets, lists, datasets itp. • Associated concept: Iterators. • Used to iterate over a container. • I.e. suppose we want to find out the number of the elements in any container.
Iterators • We would like to have a way to write even more generic functions. • I.e. suppose we want to find out the number of the elements in any container. • Or given a container, create a list of its elements.
Iterators • With a list: int elems(ListCell l) { int i = 0; for (ListCell q = l; q != null; q = q.getNext()) { i++; } return i; }
Iterators • With a tree: int elems(TreeCell t) { if (t == null) return 0; return elems(t.getLeft()) + elems(t.getRight()) + 1; }
Iterators • More general solution - define an interface of Iterator: interface Iterator { boolean hasNext(); Object next(); void remove(); }
Iterators • Now we can write (note the usage, which is typical:) int elems(Iterator i) { Object o; int res = 0; while (i.hasNext()) { o = i.next(); // here we could do something with o res++; } return res; }
Iterators • How to implement them? • Consider the class: class ArrayIntContainer { public int a[]; ... }
Iterators • First idea: Make the container class implement the iterator. class ArrayIntContainer implements Iterator { public int a[]; private int counter; public boolean hasNext() { return counter < a.length; } public Object next() { return new Integer(a[counter++]); } ArrayIntContainter() { counter = 0; } } • Disadvantages?
Iterators • First idea: Make the container class implement the iterator. class ArrayIntContainer implements Iterator { public int a[]; private int counter; public boolean hasNext() { return counter < a.length; } public Object next() { return new Integer(a[counter++]); } ArrayIntContainter() { counter = 0; } } • Disadvantages: No way to reset the counter. Only one iterator per object.
Iterators • Second idea: Create the adapter class, used only for iteration, which keeps the reference of the container object. class AIterator implements Iterator { private ArrayIntContainer aic; int counter; AIterator(ArrayIntContainer c) { aic = c; counter = 0; } public boolean hasNext() { return counter < aic.a.length; } ... } • Disadvantages?
Iterators • Second idea: Create the adapter class, used only for iteration, which keeps the reference of the container object. class AIterator implements Iterator { private ArrayIntContainer aic; int counter; AIterator(ArrayIntContainer c) { aic = c; counter = 0; } public boolean hasNext() { return counter < aic.a.length; } ... } • Disadvantages: Doesn’t work if a is private. Too large separation can result in incosistent code.
A solution! • A good solution is to use inner classes.
Inner classes • Important features: • We can declare a class inside another class. • We can return an instance of inner class to the outside world. • The instance of the inner class keeps track of the outer class object.
Inner classes class A { private int a; A() { a = 0; } public void seta(int q) { a = q; } public class B { public int geta() { return a; } } public B getB() { return new B(); } public void method() { A a = new A(); A.B b = a.getB(); a.seta(20); System.out.println(b.geta()); } }
Back to the future^O Iterators • Inner classes allow us to implement iterators in a nice way. class ArrayIntContainer { private int a[]; private class AICIterator implements Iterator { private int counter; public boolean hasNext() { return counter < a.length; } public Object next() { return new Integer(a[counter++]); } AICIterator() { counter = 0; } } public Iterator getIterator() { return new AICIterator(); } }
Generic functions interface HasIterator { Iterator getIterator(); } int elems(HasIterator i) { ... }
Generic functions interface HasIterator { Iterator getIterator(); } int elems(HasIterator c) { Iterator i = c.getIterator(); int res = 0; while (i.hasNext()) { res++; i.next(); } return res; }
Fancy stuff • Anonymous inner classes public Iterator getIterator { return new Iterator { public boolean hasNext() { ... } ... }; } • Saves the namespace.
Things to remember • General pattern of implementing adaptors - things which use class data, but are somehow separate from the class.