Stewart Stremler wrote:
And I'm talking about the official explanations of Generics that say
stuff like "suprisingly this is not the case" and "you'd think that,
but you'd be wrong".
Yes, and in those cases there are two explanations that always show up:
1) the surprise is due to limitations of the implementation or 2) the
surprise is due to the fact that programmer's intuitions are not
informed from type theory.
Perhaps an example would help. The one I keep having to explain over and
over again is this one:
public class DerivedClass extends BaseClass {
...
}
Vector<DerivedClass> foo = ....;
Vector<BaseClass> bar = foo; //no can do!
To a lot of programmers this is surprising, not intuitive, etc. But you
know what? Letting it happen would result in some *truly* unintuitive
behavior that is exactly the kind of mistake that programmers without an
education in type theory make when they fuss around with the
non-generics version of the above code.
Never bothered me. Bothered some of my collegues, but I figured that
if you're passing around raw collections, you're writing poor OO code
anyway, so why worry about it.
It's the having to wrapper your raw collections with the same stupid
type checking logic that can be done far more consistently and correctly
by computer. It's the having to put in type checking logic even when you
can prove that it is totally unnecessary, etc.
Encapsulate -- this is OOP we're talking about, yes? -- and cast. Be
sure to write a bunch of unit tests. End of problem.
Yup, so now you write wrapper methods for all the methods you use in
your collection, and then you write unit tests for all those methods....
you've now written a good dozen or more unit tests and burned through a
good chunk of your day, and in the end you've accomplished less than
what the computer can do for you in a fraction of a second. Furthermore,
it is harder for someone to verify that you haven't messed up somewhere.
All I wanted was covariant return types.
But now I read that you're not supposed to use those... Wah!
covariant return types unfortunately can get you in to trouble.
Contravariant are somewhat better, in that the nature of the trouble is
somewhat better, but still.
Um, contravariant return types are better? How does that work?
http://www.icsi.berkeley.edu/~sather/faq.html#14
And for the record Java does have covariant return types (ever since JDK
1.5 IIRC). The disadvantage of covariance is that some errors can only
be detected at runtime.
Had they put the thought they put into "synchronize" into generics, they
hopefully could have come up with something less obnoxious. Or decided
that it wasn't important (like multiple inheritance).
They actually put a LOT of thought in to generics.
Well, sorta. It's the wrong sort of thought. It's all "how to make
this happen", not "is this really a good idea for Java".
Actually, there was a lot of thought of exactly that nature put in to
it. Generics were very deliberately left out of the original
implementation of Java and held back from subsequent releases until the
powers that be thought they had a solution that was a good idea for Java.
The synchronization stuff is very weird though. I mean, what sane person
really thinks that monitors are the *only* thing that would benefit from
succinct, encapsulated, guaranteed lexical scoping.
It does the job well enough most of the time.
You misunderstand. The problem isn't with how Java manages its locks.
It's with how it doesn't provide a similar mechanism for managing any
other constrained resource.
--Chris
--
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg