How to implement an interface for two classes with an iterator

Viewed 71

I'm trying out Interfaces in java and I want to implement a common interface for a really simple stack, with pop() and push() methods and an iterator.

The problem is that I don't know how to specify the iterator in the interface. No matter which way I try, I get

Main.java:32: error: for-each not applicable to expression type
                for (Integer i : ss)
                                 ^
required: array or java.lang.Iterable
found:    Stack<Integer>

The code is as follows:

interface Stack<T> {

    boolean push(T t);

    boolean pop();
    
    //Iterator<T> iterator(); // How to indicate it needs, and will have, an iterator?
}
public class DynamicStack<T> implements Iterable<T>, Stack<T>
{
    // implementation-specific variables go here

    public DynamicStack() {
        //...
    }

    public boolean push(T t) {
        //...
    }

    public boolean pop() {
        //...
    }
    
    private class StackIterator implements Iterator<T> {
        DynamicStack<T> stk;
        //...
        
        // Iterator constructor
        private StackIterator(DynamicStack<T> stk)
        {
            //...
        }

        public boolean hasNext()
        {
            //...
        }

        public T next() throws NoSuchElementException
        {
            //...
        }

        public void remove() throws UnsupportedOperationException
        {
            throw new UnsupportedOperationException(); // I chose not to implement this one
        }
    }

    // Iterator method
    public Iterator<T> iterator()
    {
        return new StackIterator(this);
    }
}
public class StaticStack<T> implements Iterable<T>, Stack<T>
{
    // implementation-specific variables go here

    public StaticStack()
    {
        //...
    }

    public boolean push(T t)
    {
        //...
    }

    public boolean pop()
    {
        //...
    }

    private class StackIterator implements Iterator<T>
    {
        StaticStack<T> stk;
        //...

        private StackIterator(StaticStack<T> stk)
        {
            //...
        }

        public boolean hasNext()
        {
            //...
        }

        public T next() throws NoSuchElementException
        {
            //...
        }

        public void remove() throws UnsupportedOperationException
        {
            //...
        }
    }

    // Iterator method
    public Iterator<T> iterator()
    {
        return new StackIterator(this);
    }
}

Main simply does this, after creating a few stacks of each type and adding a few elements:

public static void showStuff(Stack<Integer> ss)
{
    for (Integer i : ss)
        System.out.print(i+" ");
    System.out.println();
}
2 Answers

In your test class, you are operating against Stack interface, so that is the one that needs to conform to Iterable. In this case it doesn't help if StaticStack or DynamicStack implement it if Stack does not.

To get Stack to be able to be used as Iterable just change your Stack to extend Iterable:

public interface Stack<T> extends Iterable<T> {    

    boolean push(T t);

    boolean pop();        
}

and

public class StaticStack<T> implements Stack<T>

and the code runs just fine:

public class Tester {
  public static void main(String args[]) {
    Stack<Integer> ss = new StaticStack<>();
    for (Integer i : ss)
        System.out.print(i+" ");
    System.out.println();
  }
}

You need you class to implement Iterable<T>, which has the iterator() method, which returns Iterator<T>.

Related