Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Custom Iterable, Issue with standard Interface? (http://www.velocityreviews.com/forums/t387829-custom-iterable-issue-with-standard-interface.html)

Robert Klemme 10-16-2006 02:35 PM

Custom Iterable, Issue with standard Interface?
 

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

}

Thomas Hawtin 10-16-2006 04:15 PM

Re: Custom Iterable, Issue with standard Interface?
 
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

Robert Klemme 10-16-2006 06:50 PM

Re: Custom Iterable, Issue with standard Interface?
 
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


All times are GMT. The time now is 01:45 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.