views:

304

answers:

4

I have a Collection<T>. I have a class TManager implementing an interface UManager which has a method getCollection() that needs to return a Collection<U> where U is an interface, and T is a class that implements U.

Aside from just casting it, e.g. return (Collection<U>)Tcoll;, is there a more correct way to handle this?

I control all 4 classes/interfaces here. Am I wrong in declaring UManager.getCollection as

public Collection<U> getCollection();

Should it be

public Collection<? extends U> getCollection()

?

+1  A: 

i believe you want:

public Collection<? extends U> getCollection();

You can find some official docs about this here.

@Jason, you're right. The doc doesn't call out return types explictly, but it does work. Here's an example method that demonstrates the syntax:

public Collection<? extends Throwable> getErrors() {
 return new ArrayList<Exception>();
}
saleemshafi
@saleem: the link you posted doesn't go into detail about wildcards extending return types
Jason S
+2  A: 

It should be:

public Collection<U> getCollection();

Try to avoid bounded wildcards in return types.

Subclasses would just declare the returned reference type as Collection<U> rather than Collection<T>. That would eliminate your casts.

However, if you do see the need to have a bounded wildcard in the return type, then I guess you will have to return Collection<? extends U> and won't need the cast.

notnoop
@notnoop: I did have Collection<U> and the compiler wouldn't let me return a Collection<T> without a cast.
Jason S
+2  A: 

It depends on what you need to do with the Collection. If you don't need to put anything into the returned collection, then use the extends parameter

  public interface UInterface {

         Collection<? extends UInterface> getCollection();

  }

And be done with it. If in the future you do need to add to the collection, wrapping it in a new Collection and adding all does the job, ignore the performance for nothing hit of it (extra run time performance hit for a compile time issue).

If, however, the purpose is to return a mutable collection, then you can add a type parameter to your interface:

 public interface UInterface<T extends UInterface> {

        Collection<T> getCollection();

 }

Then your implementation would be:

 public class TClass implements UInterface<TClass> {

        pubic Collection<TClass> getCollection();

 }

The problem with this approach is that you absolutely must have a type parameter at runtime to use the interface to get a mutable collection out of it, or be referencing the concrete class.

Yishai
Yes, this is an immutable collection. For mutable collections, I usually prefer passing the collection as an input parameter e.g. `public void getCollection(Collection<? super U> collection)`
Jason S
Aha, and you can return a `Collection<TClass>` rather than `Collection<? extends UInterface>` because Java 5 supports covariant return types?
Jason S
@Jason S, although Java 5 supports covariant return types, and this allows different return types based on generic parameters that are only possible because of covariant return types, this is not such a case. Collection<? extends U> and Collection<T> are not covariant, the Generic parameter is just erased at runtime. In this case it is the type parameter that lets you get it done.
Yishai
ok, thanks!!!!!
Jason S
+1  A: 

Your topicstart was a bit confusing because one-character identifiers are usually used by generic types but you explicitly mentioned about an interface and a class. So are you looking for something like this?

interface UManager<T extends UInterface> {
    Collection<T> getCollection();
}

class TManager implements UManager<TClass> {
    public Collection<TClass> getCollection() {
        return Arrays.asList(new TClass(), new TClass());
    }
}

interface UInterface {

}

class TClass implements UInterface {

}
BalusC
Not really... I suppose I could use type parameters, but I'd rather not. Good point, though! (+1)
Jason S