Re: clarifying a generics issue
On Wed, Aug 12, 2009 at 5:36 AM, Jörn Kottmann wrote: > Jörn Kottmann wrote: >> >> Marshall Schor wrote: >>> >>> I'll probably stop trying to convince others if they continue to feel >>> that the tradeoffs here should be in the direction of returning only >>> specific types (disallowing users from specifying downcasting in that >>> manner), versus using types of the form T extends X, >>> which allows users to specify downcasting. >>> >> >> The case of FSIndexRepository is maybe more clear >> then the other cases in our API. >> >> With down casting it could be changed to >> >> interface FSIndexRepository { >> FSIndex getIndex(String label); >> FSIterator getAllIndexedFS(Type aType); >> ... >> } >> >> and then a user could write >> >> FSIndex index = repo.getIndex(...); >> FSIterator it = repo.getAllIndexedFS(...); > > Any opinions on this ? Right now the class is not generified but I > would like to change that before the release. > I say no since like our other discussions, I don't like cases where there's no guarantee of correctness. A user can write: FSIterator it = repo.getAllIndexedFS(someNonAnnotationTypeCode); and it would compile even though it doesn't make sense. Something like this for JCas, on the other hand, does make sense to me: FSIterator getAllIndexedFS(Class jcasType) which is called like FSIterator it = jcas.getAllIndexedFS(MyAnnotationType.class); -Adam
Re: clarifying a generics issue
Jörn Kottmann wrote: > Jörn Kottmann wrote: >> Marshall Schor wrote: >>> I'll probably stop trying to convince others if they continue to feel >>> that the tradeoffs here should be in the direction of returning only >>> specific types (disallowing users from specifying downcasting in that >>> manner), versus using types of the form T extends X, >>> which allows users to specify downcasting. >>> >> The case of FSIndexRepository is maybe more clear >> then the other cases in our API. >> >> With down casting it could be changed to >> >> interface FSIndexRepository { >> FSIndex getIndex(String label); >> FSIterator getAllIndexedFS(Type aType); >> ... >> } >> >> and then a user could write >> >> FSIndex index = repo.getIndex(...); >> FSIterator it = repo.getAllIndexedFS(...); > Any opinions on this ? Right now the class is not generified but I > would like to change that before the release. > > Jörn Will our average user know what this means? If you think the answer to that is "yes", then I'm for it. I personally believe the answer is probably "no". --Thilo
Re: clarifying a generics issue
Jörn Kottmann wrote: Marshall Schor wrote: I'll probably stop trying to convince others if they continue to feel that the tradeoffs here should be in the direction of returning only specific types (disallowing users from specifying downcasting in that manner), versus using types of the form T extends X, which allows users to specify downcasting. The case of FSIndexRepository is maybe more clear then the other cases in our API. With down casting it could be changed to interface FSIndexRepository { FSIndex getIndex(String label); FSIterator getAllIndexedFS(Type aType); ... } and then a user could write FSIndex index = repo.getIndex(...); FSIterator it = repo.getAllIndexedFS(...); Any opinions on this ? Right now the class is not generified but I would like to change that before the release. Jörn
Re: clarifying a generics issue
On Tue, Aug 11, 2009 at 10:44 AM, Jörn Kottmann wrote: > Adam Lally wrote: >> > Lets say we have an interface Box{Number getNumber()} > then we could have a class BoxImpl implements Box{Integer getNumber(){...}}. > > Now I only would have to cast once > Box box = ...; > BoxImpl boxImpl = (BoxImpl) box; > > now > Integer number = boxImpl.getNumber() > would work. Sure if you do the same for CAS and CASImpl > you safe lots of casts. > > The same does not work for a getNumbers which > returns a List or Iterator > without also allowing down casting. > Well, true, but it does not really create an analogous solution if you do: interface Box{List getNumberList()} class BoxImpl{List numberList()} Because a client could call List x = box.getNumberList() whether or not box was actually a BoxImpl. -Adam
Re: clarifying a generics issue
Adam Lally wrote: On Mon, Aug 10, 2009 at 9:00 PM, Marshall Schor wrote: Here's a new thread to discuss just one particular issue - a generics tradeoff. In other posts, people have expressed misgivings about letting users "downcast" List to List, if it cannot be *guaranteed* at compile time that this is valid. Here's a simple example, for instance, using two built-in Java classes: Number Integer (a subtype of Number) If we have a method which returns a List, and you happen to know it only contains Integers, and you want to use a for-each on it with a method that only exists in the Integer class, you have to do manual casting within the loop. An alternative might have been to do: List numbers = ...; List int_version = numbers; // not allowed, gives compile error So once we're given the "numbers" object, as far as I can see, we're stuck with its typing. (Please tell me if I'm wrong here). I see that there is a trade-off between specifying return types as specific types, and specifying them as T extends X, and letting the user specify a possibly incorrect downcast. The tradeoff on the plus side is that the user gets to write the new style for-each loops, and have code without casts inside loops, etc., and on the minus side, the user when doing this gets that warning about the possibility that at runtime a casting error could be thrown. But of course, that same casting error could be thrown in restricted style, too, at the point of the explicit user cast. I'll probably stop trying to convince others if they continue to feel that the tradeoffs here should be in the direction of returning only specific types (disallowing users from specifying downcasting in that manner), versus using types of the form T extends X, which allows users to specify downcasting. I'd be interested in any literature pointers discussing this trade-off issue, if anyone has good ones :-) One other way to look at this - why are Collections any different than methods that return single elements? If I have a method Number getNumber() and I "know" in some situation that the Number is really an Integer, should I be able to call: Integer x = getNumber()? Normally such a thing is not allowed without an explicit cast. And for me at least I just take that for granted as part of what a strongly-typed language does, so it's very bizarre to think of it not doing that. Lets say we have an interface Box{Number getNumber()} then we could have a class BoxImpl implements Box{Integer getNumber(){...}}. Now I only would have to cast once Box box = ...; BoxImpl boxImpl = (BoxImpl) box; now Integer number = boxImpl.getNumber() would work. Sure if you do the same for CAS and CASImpl you safe lots of casts. The same does not work for a getNumbers which returns a List or Iterator without also allowing down casting. Jörn
Re: clarifying a generics issue
On Tue, Aug 11, 2009 at 7:50 AM, Marshall Schor wrote: > A small correction: allowing downcasting doesn't generate a warning > about unchecked casting. > > Here's a small test case in case you want to play with this: > > package generics; > > import java.util.List; > > public class TestG { > > class Box { // version returning down-castable thing > U get() {return null;} > List getL() {return null;} > } > > class StrictBox { // version returning just type T > T get() {return null;} > List getL() {return null;} > } > > Box box = new Box(); > StrictBox sbox = new StrictBox(); > > void test() { > // returning elements > Number n = box.get(); // OK > Integer n2 = box.get(); // OK > > Number sn = sbox.get(); // OK > Integer sn2 = sbox.get(); // fails > Integer sn3 = (Integer) sbox.get(); // OK > > // returning lists > List ln = box.getL(); // OK > List ln2 = box.getL(); // OK > > List sln = sbox.getL(); // OK > List sln2 = sbox.getL(): // fails, no fix available > } > } > For a complete picture you should also try to implement the methods to return something other that null. For example how to you implement U get() such that it returns an instance of U regardless of what U is? You could only do this with a typecast. And you'd have to expectation that the typecast would actually succeed. -Adam
Re: clarifying a generics issue
On Mon, Aug 10, 2009 at 9:00 PM, Marshall Schor wrote: > Here's a new thread to discuss just one particular issue - a generics > tradeoff. > > In other posts, people have expressed misgivings about letting users > "downcast" List to List, if it cannot be > *guaranteed* at compile time that this is valid. > > Here's a simple example, for instance, using two built-in Java classes: > Number > Integer (a subtype of Number) > > If we have a method which returns a List, and you happen to know > it only contains Integers, and you want to use a for-each on it with a > method that only exists in the Integer class, you have to do manual > casting within the loop. > > An alternative might have been to do: > List numbers = ...; > List int_version = numbers; // not allowed, gives compile error > > So once we're given the "numbers" object, as far as I can see, we're > stuck with its typing. (Please tell me if I'm wrong here). > > I see that there is a trade-off between specifying return types as > specific types, and specifying them as T extends X, and letting the user > specify a possibly incorrect downcast. The tradeoff on the plus side is > that the user gets to write the new style for-each loops, and have code > without casts inside loops, etc., and on the minus side, the user when > doing this gets that warning about the possibility that at runtime a > casting error could be thrown. But of course, that same casting error > could be thrown in restricted style, too, at the point of the explicit > user cast. > > I'll probably stop trying to convince others if they continue to feel > that the tradeoffs here should be in the direction of returning only > specific types (disallowing users from specifying downcasting in that > manner), versus using types of the form T extends X, > which allows users to specify downcasting. > > I'd be interested in any literature pointers discussing this trade-off > issue, if anyone has good ones :-) > One other way to look at this - why are Collections any different than methods that return single elements? If I have a method Number getNumber() and I "know" in some situation that the Number is really an Integer, should I be able to call: Integer x = getNumber()? Normally such a thing is not allowed without an explicit cast. And for me at least I just take that for granted as part of what a strongly-typed language does, so it's very bizarre to think of it not doing that. -Adam
Re: clarifying a generics issue
Marshall Schor wrote: I'll probably stop trying to convince others if they continue to feel that the tradeoffs here should be in the direction of returning only specific types (disallowing users from specifying downcasting in that manner), versus using types of the form T extends X, which allows users to specify downcasting. The case of FSIndexRepository is maybe more clear then the other cases in our API. With down casting it could be changed to interface FSIndexRepository { FSIndex getIndex(String label); FSIterator getAllIndexedFS(Type aType); ... } and then a user could write FSIndex index = repo.getIndex(...); FSIterator it = repo.getAllIndexedFS(...); Jörn
Re: clarifying a generics issue
A small correction: allowing downcasting doesn't generate a warning about unchecked casting. Here's a small test case in case you want to play with this: package generics; import java.util.List; public class TestG { class Box { // version returning down-castable thing U get() {return null;} List getL() {return null;} } class StrictBox { // version returning just type T T get() {return null;} List getL() {return null;} } Box box = new Box(); StrictBox sbox = new StrictBox(); void test() { // returning elements Number n = box.get(); // OK Integer n2 = box.get(); // OK Number sn = sbox.get(); // OK Integer sn2 = sbox.get(); // fails Integer sn3 = (Integer) sbox.get(); // OK // returning lists List ln = box.getL(); // OK List ln2 = box.getL(); // OK List sln = sbox.getL(); // OK List sln2 = sbox.getL(): // fails, no fix available } } -Marshall Marshall Schor wrote: > Here's a new thread to discuss just one particular issue - a generics > tradeoff. > > In other posts, people have expressed misgivings about letting users > "downcast" List to List, if it cannot be > *guaranteed* at compile time that this is valid. > > Here's a simple example, for instance, using two built-in Java classes: > Number > Integer (a subtype of Number) > > If we have a method which returns a List, and you happen to know > it only contains Integers, and you want to use a for-each on it with a > method that only exists in the Integer class, you have to do manual > casting within the loop. > > An alternative might have been to do: > List numbers = ...; > List int_version = numbers; // not allowed, gives compile error > > So once we're given the "numbers" object, as far as I can see, we're > stuck with its typing. (Please tell me if I'm wrong here). > > I see that there is a trade-off between specifying return types as > specific types, and specifying them as T extends X, and letting the user > specify a possibly incorrect downcast. The tradeoff on the plus side is > that the user gets to write the new style for-each loops, and have code > without casts inside loops, etc., and on the minus side, the user when > doing this gets that warning about the possibility that at runtime a > casting error could be thrown. But of course, that same casting error > could be thrown in restricted style, too, at the point of the explicit > user cast. > > I'll probably stop trying to convince others if they continue to feel > that the tradeoffs here should be in the direction of returning only > specific types (disallowing users from specifying downcasting in that > manner), versus using types of the form T extends X, > which allows users to specify downcasting. > > I'd be interested in any literature pointers discussing this trade-off > issue, if anyone has good ones :-) > > -Marshall > > >