The Artima Developer Community
Sponsored Link

Weblogs Forum
Why no <T super Fruit> ?

7 replies on 1 page. Most recent reply: Jun 26, 2006 2:14 AM by maurizio cimadamore

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 7 replies on 1 page
Bruce Eckel

Posts: 875
Nickname: beckel
Registered: Jun, 2003

Why no <T super Fruit> ? (View in Weblogs)
Posted: Nov 9, 2005 8:18 AM
Reply to this message Reply
Summary
I'm hoping this is an obvious one and that my brain is just fried from over-generification.
Advertisement

I haven't even found a mention of supertype bounds in any of the basic references, except with the use of wildcards. Perhaps the reason is so apparent that no one even points it out, but I hope I can at least see an example of why this is.

You can say:


class SubtypeBound<T extends Fruit> {}
But you can't say:

class SupertypeBound<T super Fruit> {}

Why not?


Adam Kiezun

Posts: 4
Nickname: akiezun
Registered: Nov, 2005

Re: Why no <T super Fruit> ? Posted: Nov 9, 2005 9:05 AM
Reply to this message Reply
It would be pretty useless, I think. The only operations you could perform on those Ts inside the SupertypeBound class are those that are present on Object.

With <T extends Fruit> you know that every T in the class has all the goodness of fruitness.

Noam Tamim

Posts: 26
Nickname: noamtm
Registered: Jun, 2005

Re: Why no <T super Fruit> ? Posted: Nov 9, 2005 9:55 AM
Reply to this message Reply
It doesn't look ok:
- It's a bad design when a base class references its derived classes; this is not the case here, but the usage is.

- I can't think of a reasonable scenario.

- Like Adam has pointed out, you'll only be able to invoke Object methods on the pointer (Object is a super of Fruit).

When I think about it, this last point is the major one.

Noam.

Martin Odersky

Posts: 84
Nickname: modersky
Registered: Sep, 2003

Re: Why no <T super Fruit> ? Posted: Nov 10, 2005 6:58 AM
Reply to this message Reply
Lower bounds <T super Fruit> would in fact be very useful as method bounds. So not including them in Java 1.5 was an oversight, I think. For instance, consider a generic class List<A> of immutable lists with an append method. Here's how one would write it without lower bounds:
  class List<A> {
    List<A> append(List<A> that) { ... }
  }

The problem with that method is that the type parameter A appears contravariantly. Hence, you cannot apply append to lists whose type is not known precisely. E.g.
  List<Fruit> myFruits;
  List<? extends Fruit> yourFruits;
  yourFruits.append(myFruits) // ERROR!!

This behaviour seems strange because our lists are immutable; Nevertheless there are still operations which are `forgotten' when the list type parameter is a wildcard.

How can we remedy the situation? With a lower bound, one could write the list class as follows:
  class List<A> {
    <B super A> List<B> append(List<B> that) { ... }
  }

In other words, we have generalized append, so that it accepts as parameters lists of an arbitrary supertype of the list element type A and returns lists of the same type. Technically speaking, the type parameter A now appears in covariant position, and therefore append is not forgotten as a member of lists with wildcard type arguments.
  yourFruits.append(myFruits)

would work perfectly, and would give a List<Fruit>.
  apples.append(oranges)

would work also, and would again give a list of fruits.

Lower bounds are used extensibely in Scala's libraries. Scala has declaration site-variance instead of wildcards. I.e. you can define that your lists are covariant by prefixing the type parameter with a `+' sign:
  // Scala code
  class List[+A] {
    def append[B >: A](that: List[B]): List[B] = ...
  }

In our experience the combination of declaration-site variance and lower bounds is a great guide in making variances in libraries correct and consistent. In Scala, one would first decide that lists are covariant. More likely than not one would then give the first, erroneous definition of append:
  // Scala code
  def append(that: List[A]): List[A] = ...

When compiling the List class, the scala compiler would then complain that A is declared to be covariant, but appears contra-variantly in append. Prompted by this error, the programmer would then put in the lower bound (he needs to be educated about this, of course, but essentially the same trick works in many variance problems).

Bruce Eckel

Posts: 875
Nickname: beckel
Registered: Jun, 2003

Re: Why no <T super Fruit> ? Posted: Nov 10, 2005 7:19 AM
Reply to this message Reply
Thanks, Martin. This is the kind of helpful analysis I was hoping for.

Adam Kiezun

Posts: 4
Nickname: akiezun
Registered: Nov, 2005

Re: Why no <T super Fruit> ? Posted: Nov 10, 2005 10:45 AM
Reply to this message Reply
Thanks Martin.

Kannan Goundan

Posts: 18
Nickname: cakoose
Registered: Nov, 2005

Re: Why no <T super Fruit> ? Posted: Nov 16, 2005 11:16 PM
Reply to this message Reply
Would it be correct to say that "<T super S>" can only be useful when both "T" and "S" are type parameters?

Also, with Scala's declaration-site variance annotations, can you write a List type that works like Java's, where the same object can be used read-only in covariant contexts and write-only in contravariant contexts?

maurizio cimadamore

Posts: 1
Nickname: maurizio
Registered: Jun, 2006

Re: Why no <T super Fruit> ? Posted: Jun 26, 2006 2:14 AM
Reply to this message Reply
Lower bounds on type variables do not fit very well with the JDK5.0 type inference algorithm; consider the following method declaration:

<Z super Integer> void m(Z z) { ... }

and the following method call:

m(new Integer(5));

You can see that we have many possible results for the type inference algorithm; the type variable Z could in fact be inferred to be either Integer, Number or Object. I think that the decision not to allow the programmer to declare lower bounds on type variables is not to deal with such cases.

A closer look to the JLS (3rd edition) give us a "clue" when talking about wildcard type declarations (4.5.1):

"Unlike ordinary type variables declared in a method signature, no type inference is required when using a wildcard. Consequently, it is permissible to declare lower bounds on a wildcard"

Flat View: This topic has 7 replies on 1 page
Topic: Why no <T super Fruit> ? Previous Topic   Next Topic Topic: New Cat Release and Documentation

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use