In the interest of fairness to Good Old Java, this is not as much of a
show-stopper as the examples make it appear.

On Feb 13, 10:14 pm, Jeff Grigg <jeffgr...@charter.net> wrote:
> The problem is that when you use method chaining on classes that
> extend other classes and which add methods, you MUST always call
> subclass methods before calling superclass methods -- otherwise it
> won't compile.

First, we can go a tad further than the parent post's example; as Jeff
showed, even though this
        new Sub().setSubStuff().setBaseStuff();
will compile, this
        new Sub().setBaseStuff().setSubStuff();
will not. Even worse, this
        Sub badSub = new Sub().setSubStuff().setBaseStuff();
won't either!

Oh, horrors! Java is completely broken!  (I'm kidding! ;-)

Back in Java 101, we learned that Java allows implicit upcasting, but
requires explicit downcasting. The compiler barfs on the second line
of this:
        Base stealthSub = new Sub();
        Sub notSub = stealthSub;
but uncomplaingly takes this:
        Base stealthSub = new Sub();
        Sub notSub = (Sub) stealthSub;
because the programmer took responsibility for guaranteeing the
appropriate relationship.

So, back to the original examples, this:
        Sub badSub = new Sub().setSubStuff().setBaseStuff();
fails because in the general case setBaseStuff() might really return
an instance of Base that is incompatible with Sub. But the programmer
can write code that explicitly states her/his intentions and gives the
compiler a promise of type-safe behavior, as in:
        Sub goodSub = (Sub) new Sub().setSubStuff().setBaseStuff();

The same solution applies to the chained methods; I simply guarantee
the compiler that I haven't broken the "chain of possession" with a
cast, either for the assignment to a variable of type Sub:
        Sub goodSub = (Sub) new Sub().setSubStuff().setBaseStuff();
or within the sequence of chained method calls:
        ((Sub) new Sub().setBaseStuff()).setSubStuff();
both of which DO compile.

So, its a bit of an exaggeration to imply that we CAN'T call Sub
methods first. We simply have to be explicit when the instance sheds
its Base overcoat. (I'm not going to mention monads here! ;-)

Do I think this solution is beautiful and graceful and effortless? Not
really. But it does allow us:
- to compile our code,
- to talk fearlessly about the various orderings of builder method
calls and whether there are some good practice statements waiting to
emerge,
- to calmly examine new language proposals while continuing to write
and compile code that is explicit and works, and,
- (most importantly, IMHO) to avoid completely changing the meaning of
void from "nothing will be returned".

I regard the redefinition of void to be a much greater threat to the
readability of Java than the need to insert an explicit cast now and
then.

-jn-

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to javaposse@googlegroups.com
To unsubscribe from this group, send email to 
javaposse+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to