Custom Iterable, Issue with standard Interface?

R

Robert Klemme

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();

}
 
T

Thomas Hawtin

Robert said:
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
 
R

Robert Klemme

Thomas said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top