|
Re: What Are Your Java Pain Points, Really?
|
Posted: Feb 17, 2007 9:21 PM
|
|
> > > stuff.atKeyPut(think1,thing2) > > > > I'd have no problem with such a new method being created. > > Maybe you can suggest it and see what might actually > > y happen. It is strange how hindsight is 20/20 > > Lots of folks had this "hindsight" the year java was > released. Bloch actively defended it when attacked for it > (by a colleague of mine who is a Smalltalk expert) at the > unveiling at JavaOne many years ago. Apparently, nobody > at Sun cares.
Josh doesn't work for Sun any longer, so his voice is less loud in this community. He can be quite overbearing because he really is confident in his capabilities. You have to give him technical arguments, not emotional ones to get any form of agreement though.
> > Casting is a necessary evil. > > No its not.
It is in a statically typed language and in particular in for narrowing and in method overloading implementations as my example demonstrated. Sure, you don't need it for narrowing assignments. But widening does require casting.
I can tell that you are not a fan of method overloading. That's a pretty subjective topic with many pros and cons. The point is that Java has method overloading. It has static typing. This means that casting is a requirement to keep from posing unnecessary restrictions on what the programmer can actually do in their software.
Sure, there are alternatives. Classes could be designed with factory methods which cast various things. It could be that narrowing could be automatic on assignment, but it might now actually be the designed behavior, so I still find it better to need to do it explicitly in many cases.
> I find it really interesting that your defense of casting > involves method overloading. Seems that bad features tend > to encourage additional bad featiures. This would be a > non-issue if you were to use a more descriptive name.
The point is that Java has static typing and allows method overloading, plain and simple. Because of that, there are some things that are only possible through casting. One of those, is this specific narrowing. Base is not a Renderable, so when a Base subclass implements Renderable, the narrowing must be explicitly specified to make sure that the right method is called. The parenthesis are the only extra characters in
showRenderable( obj )
vs
show( (Renderable)obj );
> > public interface Displayer { > > public void show( Base b ); > > public void show( Renderable r ); > > } > > > In the above situation, how do you tell which > > Displayer.show() to call for instances of Bar? > > You pick better names like 'render" for showing > renderables and showBase for base. Again, you're using > one rotten feature to justify the use of another.
It's your view (and perhaps others) that method overloading is a "rotten" feature. I think it improves readability. I do try and use useful variable names. But, I'm really not sure that you see that this narrowing makes the called method unambiguous.
dsp.show( vw )
vs
dsp.show( (Renderable)vw )
really makes it clear which one we are calling. It's only the widening binding that really creates the problem.
public void handlePaint( Renderable rend ) {
dsp.show(rend);
}
should not create problems for understanding which show is called. The most narrow binding (closest type) is used.
> > This is a very common pattern that shows up in GUI > > applications. > > Not my GUI applications it doesn't.
The use of varied rendering doesn't show up?
> > In some cases, you might need to call the Base version > and > > in others the Renderable version. Casting makes that > > possible. > > At the point that you cast - you are naming the method you > want explicitly. There is zero advantage in the methods > having the same name at this time. It is two facets of > the same activity.
Well the subtle side effect, is that there might be several (or hundreds) of method calls to "show(Base)" which I can't or don't want to edit to say "showRenderer(...)". In many cases, I've been able to change a view method parameter types and it still compiles without such a huge editing impact. And it many cases, I might be using Generics anyway, and those I can change the Generic from Base to Renerable and get the correct mapping of which show() to call and get reuse without having to create parallel copies of some code just to use it for Base and Renderable types.
> > The simple fact that typing is that explicit means that > > assignment represents a narrowing operation. Casting lets > > you agree with the compiler how narrow you want to go. > > I already told it how narrow I want to go in the variable > declaration or the method interface description. I don't > care to tell it again.
But in this case, you have a class that implements an interface. There is no logical narrowing that can occur. It must be specified explicitly because the method signatures create an ambiguity that must be resolved.
> > For the most obtuse and complicated cases it has not near > > the knowledge that you do about your intent and needs. > > You're going to have to come up with an example that > doesn't involve method disambiguation caused by > overloading to convince me.
Okay, but I think you'll have to come to grips with the fact that overloading exists in Java, plain and simple. It was a design decision that was made. Because it's there, casting is necessary for method disambiguation. Because casting has to exist there, it is, I think less surprising to require it for assignment narrowing as well.
> > In general, Java language rules provide the ability to > > solve many different classes of problems which don't > occur > > in other untyped or dynamically typed languages. > > Read that again. "Java provides the power to solve the > problems caused by Java?" Now read that in your best John > Stewart voice.
Humm, you might be understanding the issues I am trying to bring out better than I perceive. Yes, Java has language features that are related to each other. Because of method overloading, disambiguation has to be possible with casting. Because Casting exists for this reason, it can be used as a "tool" to solve other types of type "matching".
All of this, stacks up into the feature set of the language. I, personally find the APIs, cross platform portability, the stability of my applications due to GC (no explicit memory management), the features of threading and the new memory model to be far and away above and negatives which those "features" might seem to create.
Because I can reason through the dependency graph of these features, perhaps I'm not stressed about any particular "feature" and it's impact on my software.
The language features which I do find myself worrying more about these days are related to autoboxing. Autoboxing creates some object replacements which can change the mutability of certain values if you are not careful.
|
|