Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / January 2007

Tip: Looking for answers? Try searching our database.

java class heirarchy matching?

Thread view: 
falcon - 16 Jan 2007 03:55 GMT
I have a heirrarchy of classes that is basically used to create a tree
of objects.  I then want to 'evaluate' that tree of objects using
functions that are outside those classes (typically OO programmers
would probably make those functions methods of objects in the tree).

It seems to me that the function which matches the object tree is not
matching correctly.  Following is a simplified version of my test code:

abstract class Root{
    public abstract Root[] getRoots();

    public String toString(){
        StringBuffer str = new StringBuffer();
        for(int i=0;i<getRoots().length;i++)
str.append(getRoots()[i].toString());
        return " ("+this.getClass().getSimpleName()+ str+ " )";
    }
}

class Leaf1 extends Root{
    public Root[] getRoots(){ return new Root[]{}; }
}

class Leaf2 extends Root{
    public Root[] getRoots(){ return new Root[]{}; }
}

class LeafPlus extends Root{
    private Root a,b;
    public LeafPlus(Root ra, Root rb){ a=ra; b = rb; }
    public Root[] getRoots(){ return new Root[]{a,b}; }
}

class LeafMult extends Root{
    private Root a, b;
    public LeafMult(Root ra, Root rb){ a=ra; b = rb; }
    public Root[] getRoots(){ return new Root[]{a,b}; }
}

class Calculate{
    public static int value(Leaf1 l){return 1;}
    public static int value(Leaf2 l){return 2;}
    public static int value(LeafPlus l){return
Calculate.value(l.getRoots()[0])+Calculate.value(l.getRoots()[1]);}
    public static int value(LeafMult l){return
Calculate.value(l.getRoots()[0])*Calculate.value(l.getRoots()[1]);}

    //As I see it, this method should not have to exist, and even if it
does, it should never be called
    public static int value(Root l){return 100;}
}

public class TestCases {

    public static void main(String argv[]){

        //Print out the tree, see the result below
        System.out.println(new Leaf1());
        System.out.println(new Leaf2());
        System.out.println(new LeafPlus(new Leaf1(),new Leaf2()));
        System.out.println(new LeafMult(new Leaf1(), new Leaf2()));

        //Print out the result of the evaluation, see the result below
        System.out.println(Calculate.value(new Leaf1()));
        System.out.println(Calculate.value(new Leaf2()));
        System.out.println(Calculate.value(new LeafPlus(new Leaf1(),new
Leaf2())));
        System.out.println(Calculate.value(new LeafMult(new Leaf1(), new
Leaf2())));
    }
}

//Result
(Leaf1 )
(Leaf2 )
(LeafPlus (Leaf1 ) (Leaf2 ) )
(LeafMult (Leaf1 ) (Leaf2 ) )
1
2
200 <= I want the result to be '3' (1+2==3)
10000 <= I want the result to be '2' (1 * 2 == 2)

I have tried some variations such as making the Calculate class
non-static, which still doesn't give the answer I expect.  The
"value(Root l)" methods is called from LeafMult and LeafPlus, even
though within those methods the Root objects are correctly recognized
as either Leaf1 or Leaf2 (according to some print statements which I
took out).  Any ideas?
Patricia Shanahan - 16 Jan 2007 12:41 GMT
> I have a heirrarchy of classes that is basically used to create a tree
> of objects.  I then want to 'evaluate' that tree of objects using
> functions that are outside those classes (typically OO programmers
> would probably make those functions methods of objects in the tree).

Well, you already know the solution to your problem. Java method
selection is designed for OO progamming, and will tend to naturally do
what you need if you write your program that way.

> abstract class Root{
>     public abstract Root[] getRoots();
[quoted text clipped - 6 lines]
>     }
> }
...
> class Calculate{
>     public static int value(Leaf1 l){return 1;}
[quoted text clipped - 8 lines]
>     public static int value(Root l){return 100;}
> }

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.

Why not add an abstract "getValue" method to Root and put an
implementation in each subclass?

Patricia
falcon - 16 Jan 2007 14:46 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.
> 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"...


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.