listOf() does not compile for one item of a subtype for a supertype collection
GoogleCodeExporter opened this issue · 2 comments
GoogleCodeExporter commented
What steps will reproduce the problem?
1. Change constructor of FruitBowl to only take a list of Fruit instead of a
bounded wildcard, i.e.:
public FruitBowl(List<Fruit> contents) {
...
}
2. Change FruitBowlMaker accordingly to solve compilation errors, i.e.:
public class FruitBowlMaker {
public static final Property<FruitBowl, List<Fruit>> contents =
newProperty();
public static final Instantiator<FruitBowl> FruitBowl =
new Instantiator<FruitBowl>() {
public FruitBowl instantiate(PropertyLookup<FruitBowl> lookup) {
return new FruitBowl(lookup.valueOf(contents, listOf(
an(Apple), a(Banana)).value()));
}
};
}
3. Remove the banana, leaving only a single item in the list. Alternatively,
replace it with another apple, leaving two items but of the same type in the
list.
What is the expected output? What do you see instead?
It should compile, since an apple is a fruit, and so are two, but because of
the way Java implements Generics, listOf() now returns a List<Apple> which is
not a List<Fruit>. The exact compiler error is:
The method valueOf(Property<? super FruitBowl,V>, V) in the type
PropertyLookup<FruitBowl> is not applicable for the arguments
(Property<FruitBowl,List<Fruit>>, List<Apple>)
What version of the product are you using? On what operating system?
3.1.0 on Ubuntu 10.10 with OpenJDK 6
Please provide any additional information below.
I know this is probably a limitation of Java but the example gives the illusion
that it will work for any combination of fruit. I was also wondering what
possible workarounds there are
Thanks
Thomas
Original issue reported on code.google.com by holz.tho...@gmail.com
on 21 Jan 2012 at 11:54
GoogleCodeExporter commented
The never-ending wonders of Java Generics ...
Turns out that you can explicitly type the return type of the lastOf() function
to return a list of a super type of the one passed in, like so:
public static void howToMakeCollectionsWithValuesOfASingleSubtype() {
FruitBowl bowl = make(a(FruitBowl, with(contents,
MakeItEasy.<Fruit>listOf(a(Banana))
)));
}
The only caveat, as far as I know, is that the function needs to be qualified
with the class name in front even with a static import.
Original comment by holz.tho...@gmail.com
on 22 Jan 2012 at 1:15
npryce commented
It works if you don't remove the bounded wildcard in the constructor. This isn't something that can be fixed in the listOf function.