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 / June 2007

Tip: Looking for answers? Try searching our database.

Overriding Generics

Thread view: 
Bryan - 31 May 2007 20:06 GMT
Does anyone know why one can't override the following method

public List<Foo> getFooList()

with something like this

public List<Bar> getFooList()

if Bar extends Foo?

Thanks in advance!!!
Daniel Dyer - 31 May 2007 20:11 GMT
> Does anyone know why one can't override the following method
>
[quoted text clipped - 5 lines]
>
> if Bar extends Foo?

Because List<Bar> is not a sub-type of List<Foo>, even if Bar is a  
sub-type of Foo.

ArrayList<Foo> is a sub-type of List<Foo>, as is LinkedList<Foo>.

To extend the method as you wish, the super-type method would have to be:

    List<? extends Foo> getFooList()

Then List<Bar> getFooList() would be fine.

Dan.

Signature

Daniel Dyer
http//www.uncommons.org

Tom Hawtin - 31 May 2007 20:36 GMT
>> Does anyone know why one can't override the following method
>>
[quoted text clipped - 14 lines]
>
>     List<? extends Foo> getFooList()

Alternatively, you could make the type containing the method generic:

interface Base<T extends Foo> {
   List<T> getFoos();
}

interface Derived extends Base<Bar> {
   List<Bar> getFoos();
       // (not actually necessary to declare in this case)
}

Tom Hawtin
Bryan - 31 May 2007 22:26 GMT
Daniel -- Your suggestion fixed my problem... thanks!

Tom -- Could you elaborate on your suggestion a little more?  I'm not
exactly sure what you're suggesting...

Thanks!
Twisted - 31 May 2007 23:06 GMT
> > Does anyone know why one can't override the following method
>
[quoted text clipped - 16 lines]
>
> Then List<Bar> getFooList() would be fine.

Yup. And if anyone's wondering why List<Bar> is not a sub-type of
List<Foo>, it's because you can't do everything with a List<Bar> that
you can with a List<Foo> -- in particular, you can't put a Foo that is
not a Bar into the List<Bar>, but you can put it into the List<Foo>,
using List.add().

The bounded wildcard <? extends Foo> does, unlike <Foo>, act as a
supertype of any <Thing> where Thing extends Foo. A consequence is
that methods of List that accept a Foo work on a List<Foo> but not a
List<? extends Foo>, or else you might put a Bar in a List<Baz> or a
Baz in a List<Bar> (where both Bar and Baz extend Foo) that way, or a
vanilla Foo in either. Essentially, with containers, the Container<?
extends Foo> generic is effectively read-only. Code can assume objects
pulled out are Foos, but not that vanilla Foos or any particular
subtype can go in.
Bryan - 01 Jun 2007 15:55 GMT
Another generics overriding question -- say I have the method below:

public List<? extends Foo> getFooList() { ... }

When I try and do this:

List<Foo> l = getFooList();

I get the following error:

Type mismatch: cannot convert from List<capture-of ? extends Foo> to
List<Foo>

Can anyone explain this to me?  Thanks!
Lew - 01 Jun 2007 17:54 GMT
> Another generics overriding question -- say I have the method below:
>
[quoted text clipped - 10 lines]
>
> Can anyone explain this to me?  Thanks!

It's pretty much the same as the other question.  You can only upcast the
result of any method to a supertype of the return type.  List<Foo> is not a
supertype of List<? extends Foo>.  So you get the error that you cannot
convert the type.

Start here:
<http://java.sun.com/docs/books/tutorial/extra/generics/index.html>

in particular, the topics
<http://java.sun.com/docs/books/tutorial/extra/generics/subtype.html>
and
<http://java.sun.com/docs/books/tutorial/extra/generics/wildcards.html>
address this matter.

Let's say the actual runtime return type of the list were 'List<FooSomeSub>'.
 Your list 'l' would allow
  l.add( new FooSomeOtherSub() );
which would violate the type safety.

The wildcard form prevents such add()s (from the referenced tutorial):
> Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.
> On the other hand, ... we can call get() and make use of the result.

Another tutorial:
<http://java.sun.com/docs/books/tutorial/java/generics/index.html>

particularly
<http://java.sun.com/docs/books/tutorial/java/generics/subtyping.html>
and
<http://java.sun.com/docs/books/tutorial/java/generics/wildcards.html>

And for the final word, the JLS:
<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.5>

<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10>
> Subtyping does not extend through generic types: T <: U does not imply that C<T> <: C<U>.

<http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.10.2>

The relevance of the subtype relationship:
<http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.5>

<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4>
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.5>
<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12>

Signature

Lew

Twisted - 01 Jun 2007 20:27 GMT
> Another generics overriding question -- say I have the method below:
>
[quoted text clipped - 10 lines]
>
> Can anyone explain this to me?  Thanks!

Basically the same problem. You could return a List<Bar> from
getFooList, then put a vanilla Foo into it via l, if you could assign
the List<? extends Foo> to l. And then somewhere else in your code,
far, far away from the real error in space and time, something would
blow up when it retrieved Bars from the list and stumbled over the
vanilla Foo. You'd get a ClassCastException from nowhere near the real
source of the problem, and possibly after a long time had gone by and
the culprit's trail had grown cold. Indeed, it might not blow up for
days; the bad item might lurk in the list like a ticking bomb while
it's ignored, then serialized to disk, then loaded in another session,
then seralized again to stream over the net to a completely different
process running on a different machine ...

Java's type checking and rules may seem strict and sometimes
mysterious, but they are designed to stop that kind of thing and make
sure that when bugs do occur, they usually produce their symptoms
close to the actual site of the logic error, making it far quicker and
far easier to debug.

Two things to further reduce the occurrence of symptoms widely
separated from causes:
* Think carefully before subverting the type system, e.g. by passing
lots of stuff around as Objects, not using generic type parameters on
containers, or sprinkling code liberally with
@SuppressWarnings("unchecked") -- this doesn't mean never do those,
but keep stuff like that to a minimum and to where you can mentally
"prove" the type-correctness of the code. I tend to limit this sort of
thing to the few cases where the type semantics can't be expressed in
Java and the compiler can't prove it's type-correct, but I know for a
fact it's safe -- and those occasions are rare indeed. Usually the
right <? extends Foo> in place of <Foo> or similar is all that's
needed.
* When using collections or otherwise storing objects for an
indeterminate time before use, check for invalid objects (nulls if
invalid, wrong type, NaNs or other unwanted float values, etc.) and
throw an exception eagerly instead of letting whoever ends up
retrieving the object have to cope with it. This is especially
critical when a parameter is stored in an object's fields or a
collection and it shouldn't be null. A single "if (foo == null) throw
new NullPointerException()" in the constructor or whatever method can
save many an hour of grief and hair-pulling down the line. This also
applies if for some reason you have need to store specific types of
object in a less specific type container (or reference). For instance,
you need to store both Baz and Quux but not accept the raw supertype
Foo or other subtypes like Bar. Ideally, there's a type for just the
things you will allow in that store, so Foo has Bar and Allowed
subclasses, and Allowed has Baz and Quux, and you use a List<Allowed>.
Of course, you might not control the classes Baz and Quux (they're
another team's code, or library code, or whatever) to be able to force
this class hierarchy. Then you need to check types explicitly,
unfortunately, or find another solution (such as separate lists for
each allowed type). Many times there are elegant ways to solve these
problems using generics. For instance, when the types of two things
need to match, instead of say xList<Foo> and yList<Foo> and a possible
mismatch with a Bar in the xList and a Baz in the corresponding place
in the yList, make a Pair<T> class with a Pair(T x, T y) constructor,
getX and getY methods, etc., and use a List<Pair<? extends Foo>>. (Of
course, this can be defeated by creating Pair<Foo>s instead of
Pair<more derived type>s, but this may still be useful partly because
what's really supposed to represent a single list is now actually a
single list instead of two, and because of cases where it's fairly
heterogeneous, particularly Foo == Object and you want Pair<Integer>s,
Pair<String>s, etc., like for some kind of comparison and validation
of heterogeneous data nuggets. Pairs with different types presumably
represent a bug in the code putting the pairs in, or validating input,
rather than one of the mismatches you want to detect later.)


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.