Yeah this is a tricky one ... But you're right that the API is "?
extends List<String>" so you can pass in NSArray<String>, which is a
pretty common implementation. You also can't necessarily just assume
people can declare their vars as List<String> instead of
NSArray<String> because you don't know where that var came from (the
general case is that you really do want it to be enforced as <String,
NSArray<String>>). Basically, this method declaration makes it easy
and flexible for people passing in params, but it makes it really
complicated to add values to that map like Andrew is finding. The
deal is that the signature is "? extends List<String>" this does NOT
mean you can just put anything that extends List<String> into the
value, rather, it means you can pass in any generic that has a List
that is a subclass of List<String>. The distinction is that if you
pass in NSArray<String> as the list, you can't just put any list into
it -- it explicitly has to be an NSArray<String>, but inside that
method, you have no idea what the ACTUAL type is. So Andrew's code is
failing because the list type he's putting in is whatever
singletonList returns, but that's not guaranteed to be match the
passed-in type.
The problem is that if the method sig is changed to <String,
List<String>> then you have to do a copy operation to convert <String,
NSArray<String>> to <String, List<String>> ... Tough call on that
one. If the method sig changes, it's annoying to people passing
values in, but as it stands, i'm not sure it's possible to put values
INTO it inside this method.
ms
On May 15, 2009, at 8:14 AM, Jim Kinsey wrote:
Hi Andrew,
I find it odd that the map should have ? extends List<String> as a
parameter as the extension ought to be unnecessary (assuming callers
are working to the List interface) - any List implementation with a
String parameter fulfills List<String>. I like generics too, but
have come across similarly gnarly counter-intuitive things. I find
that often if you think about them enough they eventually make
sense, but this one has me stumped!
I see it came from overriding the WOApplication method - and if you
don't include the parameter in this way you get a compilation error.
This can be made to go away by overriding without providing the
generic parameters, which then produces a warning which you can
annotate away:
@SuppressWarnings("unchecked")
@Override
public WORequest createRequest(String method, String aurl,
String anHTTPVersion,
Map someHeaders, NSData content,
Map someInfo) {
someHeaders.put("foo",
Collections.<String>singletonList("bar"));
I suppose you might want to use this kind of wildcard extension if
you want to pass a Map which declares an extension of List
elsewhere; e.g. if there was a calling method which was passing a
variable declared as Map<String, NSMutableArray<String>> to this
method there would be a compilation error without the wildcard;
arguably what the calling method ought to be doing though is
declaring the list it passes as Map<String, List<String>> and hiding
the concrete List implementation, negating the need for the wildcard.
e.g. works to impl rather than interface:
NSMutableDictionary<String, NSMutableArray<String>> someHeaders =
new NSMutableDictionary<String, NSMutableArray<String>>();
someHeaders.setObjectForKey(new NSMutableArray<String>("bar"),
"foo");
WORequest req = createRequest(method, aurl, anHTTPVersion,
someHeaders, content, someInfo);
vs. working just to interface:
Map<String, List<String>> someHeaders = new
NSMutableDictionary<String, List<String>>();
someHeaders.put("foo", new NSMutableArray<String>("bar"));
WORequest req = createRequest(method, aurl, anHTTPVersion,
someHeaders, content, someInfo);
Both compile to current WOApplication API; former would not if the
wildcard were to be removed from createRequest.
Could this be considered a bug in WOApplication? I believe if this
method declaration had the wildcard extension removed and any
calling methods which need to be were fixed to work to interface
rather than implementation then this problem would go away and
createRequest could be overridden and worked with generically. Easy
to say - I still find myself preferring to work directly with NS
implementations for key-value-coding / EOQualifiers...
Cheers,
Jim
On 15 May 2009, at 03:54, Andrew Lindesay wrote:
Sorry wrong method; I obviously meant "put" rather than "add" in
this example and "The method put(String,List<String>) in the type
Map<String,capture#1-of? extends List<String>> is not applicable
for the arguments (String,List<String>)" is the problem.
I've been working with generics for quite a while (and quite like
them) but this one has me stumped!
___
Andrew Lindesay
www.lindesay.co.nz
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/jim.kinsey%40bbc.co.uk
This email sent to [email protected]
http://www.bbc.co.uk
This e-mail (and any attachments) is confidential and may contain
personal views which are not the views of the BBC unless
specifically stated.
If you have received it in error, please delete it from your system.
Do not use, copy or disclose the information in any way nor act in
reliance on it and notify the sender immediately.
Please note that the BBC monitors e-mails sent or received.
Further communication will signify your consent to this.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/mschrag%40mdimension.com
This email sent to [email protected]
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com
This email sent to [email protected]