/**
 * Example iterators using separate classes that implement Iterator.
 * The best strategies (SharkB and SharkC) are those that use inner classes.
 */

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Used for main program.
 */
public class Shark {
    
    public static void main (String[] args) {
        String[] months = {"jan", "feb", "mar", "apr", "may", "jun", 
                           "jul", "aug", "sep", "oct", "nov", "dec"};
        Iterable[] sharks = {new SharkA(months), new SharkB(months), new SharkC(months)};
        for (int i = 0; i < sharks.length; i++) {
            for (Iterator it = sharks[i].iterator(); it.hasNext();)
                System.out.print(" " + it.next());
            System.out.println();
        }
    }
}

/* Separate Iterator class.
 * Remora needs access to Shark data, implying Shark data
 * is more public than desirable.
 */
class SharkA implements Iterable {
    public Object[] data;
    public SharkA (Object[] a) { data = a; }
    public Iterator iterator () {return new RemoraA(this);}
}
class RemoraA implements Iterator {
    private int index = 0;
    private SharkA shark;
    public RemoraA (SharkA s) { shark = s; }
    public boolean hasNext ()  {return (index < shark.data.length);}
    public Object next () {
        if (hasNext()) return shark.data[index++];
        else throw new NoSuchElementException();
    }
    public void remove () {throw new UnsupportedOperationException();}
}

/* Iterator as an inner class.
 */
class SharkB implements Iterable {
    private Object[] data;
    public SharkB (Object[] a) { data = a; }
    public Iterator iterator () {return new RemoraB();}
    
    private class RemoraB implements Iterator {
        private int index = 0;
        public boolean hasNext () {return (index < data.length);}
        public Object next () {
            if (hasNext()) return data[index++];
            else throw new NoSuchElementException();
        }
        public void remove () {throw new UnsupportedOperationException();}
    }
}

/* Iterator as an anonymous inner class.
 */
class SharkC implements Iterable {
    private Object[] data;
    public SharkC (Object[] a) { data = a; }
    public Iterator iterator () {
        return new Iterator () {
            private int index = 0;
            public boolean hasNext ()  {return (index < data.length);}
            public Object next () {
                if (hasNext()) return data[index++];
                else throw new NoSuchElementException();
            }
            public void remove () {throw new UnsupportedOperationException();}
        };
    }
}