...
> The problem is that the run time use of object class to pick a method
> only applies to the object containing the method, not to its parameters.
> The compiler, when processing e.g. the value calls inside the LeafMult
> value method, sees that it needs a value() method that can deal with
> Root parameter, and selects the last one in Calculate.
I'm not sure I understand. How come the following works:
System.out.println(Calculate.value(new Leaf1()));
Yet the following doesn't:
System.out.println(Calculate.value(new LeafPlus(new Leaf1(),new
Leaf2())));
In both cases, a single parameter Calculate.value is passed an object
which is either Leaf1 or Leaf2. What's more, this is known at compile
time. More surprising is the fact that when I print the type of
objects passed in to value methods, the types are identified correctly.
This is even true when value(Root r) is dispatched...the printed value
is shown as Leaf1 or Leaf2 (so why wasn't value(Leaf1/2 l) dispatched
then? Strange!
> Why not add an abstract "getValue" method to Root and put an
> implementation in each subclass?
The point of this excercise is to get a better understanding :) I'd
also like to keep a number of different Calculate classes. Basically
I'm trying to apply some lessons from functional programming. Perhaps
the two are better kept seperate.
Thanks Patricia.
Patricia Shanahan - 16 Jan 2007 15:03 GMT
>> The problem is that the run time use of object class to pick a method
>> only applies to the object containing the method, not to its parameters.
[quoted text clipped - 4 lines]
> I'm not sure I understand. How come the following works:
> System.out.println(Calculate.value(new Leaf1()));
In this case the compile time type of the parameter, "new Leaf1()" is
Leaf1. That method makes no other calls, so that resolves all the method
selection.
> Yet the following doesn't:
> System.out.println(Calculate.value(new LeafPlus(new Leaf1(),new
> Leaf2())));
The top calculateValue call, with compile time parameter type LeafPlus,
will call Calculate.value(l.getRoots()[0]) and
Calculate.value(l.getRoots()[1]).
The return type for l.getRoots(), with l of type LeafPlus, is Root. The
compiler will set up each of those calls to require a Calculate.value
with a Root parameter. Methods that don't accept any Root reference as
parameter will not be considered at all.
> In both cases, a single parameter Calculate.value is passed an object
> which is either Leaf1 or Leaf2. What's more, this is known at compile
[quoted text clipped - 3 lines]
> is shown as Leaf1 or Leaf2 (so why wasn't value(Leaf1/2 l) dispatched
> then? Strange!
You are confusing two different issues that Java distinguishes, the
compile time type of an expression, and the class of an object the
expression references at run time. When you say "print the type", you
are actually printing the run time class of the object referenced by an
expression, not the type of the expression.
>> Why not add an abstract "getValue" method to Root and put an
>> implementation in each subclass?
[quoted text clipped - 3 lines]
> I'm trying to apply some lessons from functional programming. Perhaps
> the two are better kept seperate.
It might be best to separate them until you understand how each behaves
in Java separately. There are ways of doing functional programming in
Java, but more awkwardly than in a language designed for that approach.
Generally, I find the best recipe for happy, smooth programming is to
match the programming language to the way you want to program, so that
you are going with the flow of the way the language works, rather than
fighting it.
Patricia
John Ersatznom - 16 Jan 2007 17:09 GMT
> The point of this excercise is to get a better understanding :) I'd
> also like to keep a number of different Calculate classes. Basically
> I'm trying to apply some lessons from functional programming. Perhaps
> the two are better kept seperate.
Not necessarily. Read up on "visitor pattern"...