Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / October 2006

Tip: Looking for answers? Try searching our database.

Custom Iterable, Issue with standard Interface?

Thread view: 
Robert Klemme - 16 Oct 2006 15:35 GMT
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 - 16 Oct 2006 17:15 GMT
> 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 - 16 Oct 2006 19:50 GMT
>> I have a similar situation as demonstrated below.  I cannot find a
>> proper solution to make method iterator() work properly.  It works
[quoted text clipped - 5 lines]
> 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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.