Adam Lally wrote:
> On Sat, Aug 8, 2009 at 4:57 PM, Marshall Schor<m...@schor.com> wrote:
>   
>> Jörn Kottmann wrote:
>>     
>>> On Aug 7, 2009, at 8:57 PM, Marshall Schor wrote:
>>>
>>>       
>>>> getViewIterator in CASImpl is written with the signature:
>>>>  Iterator<CAS> getViewIterator()
>>>>
>>>> If you are working with things needing CASImpl objects, you would write:
>>>>
>>>>  Iterator<CAS> s = aCas.getViewIterator();
>>>>  while (s.hasNext()) {
>>>>    CASImpl ci = (CASImpl) s.next();
>>>>      ... code using ci...
>>>>  }
>>>>
>>>> If we changed the signature to:
>>>>  Iterator<T extends CAS> getViewIterator()
>>>> then you would write:
>>>>  Iterator<CASImpl> s = aCas.getViewIterator(); // cast done inside the
>>>> support code, not here
>>>>  while (s.hasNext()) {
>>>>    CASImpl ci = s.next();  // works OK without casting
>>>>      ... code using ci...
>>>>  }
>>>>
>>>> Would it be better to have that form of the signature?
>>>>         
>>> +1, though did not know that its possible, we should check other
>>> places too
>>>       
>> +1 to checking other places :-)
>>
>> The tutorial on generics by Gilad Bracha,
>> http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf,  on page 20 near
>> the top says:
>>
>>     
>>> In general, if you have an API that only uses a type parameter T as an
>>> argument, its
>>> uses should take advantage of lower bounded wildcards (? super T).
>>> Conversely, if
>>> the API only returns T, you’ll give your clients more flexibility by
>>> using upper bounded
>>> wildcards (? extends T).
>>>       
>> There are many cases I think in our generification where the 2nd part of
>> this, returning XXX<? extends T> or a variant, is a better choice.
>>
>>     
>
> I must say I don't understand why returning something like List<?
> extends CAS> is an improvement.  Is this supposed to mean that the
> client could specify ANY subtype of CAS and it's supposed to work?  So
> someone could write:
> class MyCas implements CAS {...}
> List<MyCas> result = aCAS.getViewIterator()
> Which couldn't possibly work.  I guess it would compile but generate a
> ClassCastException at runtime.  Is that a good thing?
>
> I found an expert with a differing point of view from your expert:
> http://www.ibm.com/developerworks/java/library/j-jtp07018.html?S_TACT=105AGX02&S_CMP=EDU
>
> "Keep bounded wildcards out of return values
>
> It is sometimes tempting to use a bounded wildcard in the return type
> of a method. But this temptation is best avoided because returning
> bounded wildcards tends to "pollute" client code. If a method were to
> return a Box<? extends T>, then the type of the variable receiving the
> return value would have to be Box<? extends T>, which pushes the
> burden of dealing with bounded wildcards on your callers. Bounded
> wildcards work best when they are used in APIs, not in client code."
>   

This is a good discussion.  I didn't realize that about bounded
wildcards.  But there's another choice.

Consider the difference between <? extends T> and a form that looks like:
public <T extends AbstractCas> Iterator<T> getViewIterator() {

This latter form doesn't use a wild card, and if it is used as the
return type of the method, the return type's match for T gets used, and
this doesn't have the issue above.
So that's another choice, and that was the choice I was thinking about
in my original post, where the actual form was written incorrectly (the
correct way is above).

Here's another (probably weak) use case for returning <T extends
AbstractCas> kinds of things:  If you have part of the code which
collects views and some of these views use one form of the AbstractCas
(e.g. CASImpl) and others use the JCas form, it would be nice to be able
to put these two uses into a collection (of AbstractCas) - which is the
kind of thing AbstractCas was trying to do, I believe.

If we changed getViewIterator to return Iterator<AbstractCas>  (another
choice), that would serve the use case in the above paragraph, but then
the form
Iterator<CAS> it = aCas.getViewIterator()
would give a compile-time error.

It seems to me that <T extends AbstractCas> is a better generification,
here.

-Marshall


>  -Adam
>
>
>   

Reply via email to