Custom Iterable, Issue with standard Interface?

Discussion in 'Java' started by Robert Klemme, Oct 16, 2006.

  1. Hi,

    I have a similar situation as demonstrated below. I cannot find a
    proper solution to make method iterator() work properly. It works with
    the custom interface Iterable2 (see below). I tried several
    alternatives I could think of but to no avail (see comments in code).
    Any other ideas? Or am I running into a limitation of Iterable?
    Research did not turn up much useful information for this situation.
    Thanks for any feedback!

    Kind regards

    robert




    package generics;

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import java.util.Map.Entry;

    // does not work because: The type WrappedTest cannot extend or
    implement Iterable<? extends Map.Entry<K,V>>. A supertype may not
    specify any wildcard
    // public class WrappedTest<K, V> implements Iterable<? extends
    Map.Entry<K, V>> {
    public class WrappedTest<K, V> implements Iterable<Map.Entry<K, V>>,
    Iterable2<Map.Entry<K, V>> {

    private static class En<Ke, Va> implements Map.Entry<Ke, Va> {

    public Ke getKey() {
    return null;
    }

    public Va getValue() {
    return null;
    }

    public Va setValue( Va value ) {
    return null;
    }
    }

    private Set<En<K, V>> set = new HashSet<En<K, V>>();
    // works but not usable:
    // private Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K,
    V>>();

    public Iterator<Map.Entry<K, V>> iterator() {
    // error in this line:
    return set.iterator();
    }

    // this is ok
    public Iterator<? extends Entry<K, V>> iter() {
    return set.iterator();
    }

    // works but inheritance from Iterable<Map.Entry<K, V>> fails:
    // public Iterator<? extends Map.Entry<K, V>> iterator() {
    // return set.iterator();
    // }
    }


    package generics;

    import java.util.Iterator;

    public interface Iterable2<T> {

    public Iterator<? extends T> iter();

    }
     
    Robert Klemme, Oct 16, 2006
    #1
    1. Advertising

  2. Robert Klemme wrote:
    >
    > I have a similar situation as demonstrated below. I cannot find a
    > proper solution to make method iterator() work properly. It works with
    > the custom interface Iterable2 (see below). I tried several
    > alternatives I could think of but to no avail (see comments in code).
    > Any other ideas? Or am I running into a limitation of Iterable?
    > Research did not turn up much useful information for this situation.


    So you have an Iterator<D> but want to return it as type Iterator<B>,
    where D extends B?

    I suggest you write a proxy:

    class IteratorTypeProxy<E> implements Iterator<E> {
    private final Iterator<? extends E> target;
    public static <E> Iterator<E> create(Iterator<? extends E> target) {
    return new IteratorTypeProxy<E>(target);
    }
    private IteratorTypeProxy(Iterator<? extends E> target) {
    if (target == null) {
    throw new NullPointerException();
    }
    this.target = target;
    }
    public boolean hasNext() {
    return target.hasNext();
    }
    public E next() {
    return target.next();
    }
    public void remove() {
    target.hasNext();
    }
    }


    Note, you can't implement, say, the full ListIterator interface this
    way. add(E) and set(E) wouldn't work.

    As Iterable<B>.iterator gives an Iterator<B> instead of Iterator<?
    extends B>, the method can be overridden to return ListIterator<B>. (It
    also helps to make client code easier to read - as a rule, don't return
    wildcarded types.)

    Tom Hawtin
     
    Thomas Hawtin, Oct 16, 2006
    #2
    1. Advertising

  3. Thomas Hawtin wrote:
    > Robert Klemme wrote:
    >>
    >> I have a similar situation as demonstrated below. I cannot find a
    >> proper solution to make method iterator() work properly. It works
    >> with the custom interface Iterable2 (see below). I tried several
    >> alternatives I could think of but to no avail (see comments in code).
    >> Any other ideas? Or am I running into a limitation of Iterable?
    >> Research did not turn up much useful information for this situation.

    >
    > So you have an Iterator<D> but want to return it as type Iterator<B>,
    > where D extends B?


    Exactly.

    > I suggest you write a proxy:


    <snip/>

    I have considered that myself but would obviously prefer to not have to
    do that as I know the instances returned from the iterator are
    compatible. It just does not feel right so I thought I'd first check
    whether I overlooked some generics wizardry. But I assume there is no
    such thing and there is probably a good reason that interface Iterable
    returns an Iterator<T> and also that you cannot implement an interface
    with a wildcard. If anyone can offer insights as to why that is I'd be
    glad to learn.

    > As Iterable<B>.iterator gives an Iterator<B> instead of Iterator<?
    > extends B>, the method can be overridden to return ListIterator<B>. (It
    > also helps to make client code easier to read - as a rule, don't return
    > wildcarded types.)


    Thanks!

    Kind regards

    robert
     
    Robert Klemme, Oct 16, 2006
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Remi Bastide
    Replies:
    5
    Views:
    13,572
    elizas
    Mar 29, 2010
  2. Googmeister

    Whay aren't Strings Iterable?

    Googmeister, Oct 9, 2005, in forum: Java
    Replies:
    13
    Views:
    991
    Mike Schilling
    Oct 10, 2005
  3. Leif K-Brooks

    Word for a non-iterator iterable?

    Leif K-Brooks, Feb 6, 2005, in forum: Python
    Replies:
    5
    Views:
    388
    Terry Reedy
    Feb 7, 2005
  4. Thomas
    Replies:
    9
    Views:
    874
  5. Replies:
    2
    Views:
    366
    James Stroud
    Dec 10, 2008
Loading...

Share This Page