We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › are dynamic function calls possible
Page Index Toggle Pages: 1
are dynamic function calls possible? (Read 1446 times)
are dynamic function calls possible?
Aug 24th, 2007, 3:33am
 
I'm trying to write a generic UI class, and I need to be able to dynamically call a function by a string name, and throw exceptions if none are found.  I've seen this ability used in the controlP5 library, but I can't for the life of me figure out how to implement it.  basically the desire is this:

create a button named "test" inside my class.
create a button named "test2" inside my class.
when the test button is pressed, I want it to call the test() function in the main program (if it exists). same with test2.

The point is to be able to call a function based on a string name, and throw exceptions if it's not found.  Any help would be greatly appreciated.
Re: are dynamic function calls possible?
Reply #1 - Aug 24th, 2007, 4:12am
 
never mind. I found an old topic responded to by andi that he used reflection in java to get this functionality. off to figure it out now.
Re: are dynamic function calls possible?
Reply #2 - Aug 24th, 2007, 11:08am
 
There's much much much better ways of doing this than strings and reflection, that's really really nasty for most uses.

Create a buttonAction interface, then create implementatinos of this interface that do what you want, and then you can pass objects to the buttons, so they can call the function.
e.g.:
Code:
interface buttonAction
{
void doStuff();
}

class test implements buttonAction
{
void doStuff()
{
println("We're test!");
}
}

class test2 implements buttonAction
{
void doStuff()
{
println("We're test2!");
}
}

class button
{
buttonAction action;
button(.... , buttonAction _action)
{
// ... normal stuff...
action=_action;
}

void clicked()
{
//.. anything else you do when clicked
action.doStuff();
}
}

button buttonA,buttonB;
test testA;
test2 testB;

void setup()
{
//...
testA=new test();
testB=new test2();
buttonA=new button(... , testA);
buttonB=new button(... , testB);
}

void draw()
{
//...
}
Re: are dynamic function calls possible?
Reply #3 - Aug 26th, 2007, 10:55pm
 
Hm, not sure that I agree.  For a UI library, I think it's really stretching the limits of the purpose of inheritance when you are forced to implement an interface in order for something to respond to a mere button event, and further, to have to create a separate class just to wrap the function that you actually care about.  I suspect Sun en masse might disagree with me, which is part of why Java's UI libraries are so freaking obnoxious to use...

I personally find it much easier on the end programmer (i.e. the one using the library, not the one making it) to require only that they pass an object and the name of the method to call when they create a button.  This allows them to merely remember to call button(myObject,"methodName") rather than that they have to implement a doStuff() function that redirects the call to the function you ACTUALLY want to call, and then pass the object.  It also localizes changes in code in a more OO manner, as without using reflection, in order to attach a public function to a button, you HAVE to either alter the class that contains that function or create a connector class whose only purpose is to redirect a call from doStuff() to a particular function; using reflection, the thing that you mess with is the button, which is very local in a way that I think matches the actual real world cause/effect relationship.

Then again, feel free to disagree.  I'm one of those naysayers that always thought it was a terrible decision to excise pointers to functions from Java, and that far too many "design patterns" and best practices are really just dirty ways of hacking around this language deficiency.  So I was pretty happy when reflection came around to repair that particular lack of functionality...
Re: are dynamic function calls possible?
Reply #4 - Sep 5th, 2007, 12:20am
 
Yeah, I agree on the reflection idea.  In my opinion for a public library, I would rather not have to do all that extra work.  Just pass the function name to my object, and have that object call the function. I shouldn't have to extend it to call a simple button press, and the user shouldn't have  to know anything about the internals of my class to use it.

problem is, I don't know how to use reflection from within processing.  Here is my example code for my button event:

Code:
public class Button
{
Button(init vars)
{
//init button class
app.registerMouseEvent(this);
}

void mouseEvent(MouseEvent event){
//pass event.getID() to dynamic function with reflexive
}
}


now how would I go about using reflexive in that instance and have it call a function in the main program using invoke?
Re: are dynamic function calls possible?
Reply #5 - Sep 5th, 2007, 1:52am
 
$.02:  This would be a good place for anonymous classes.  So start with John G's approach, then filter out all the classes/references that you really don't need to keep explicit track of, and just implement them inline instead, something like:

Button A = new Button(...,
 new buttonAction() {
   void doStuff() {
     println("We're test!");
   }
 }
);
Re: are dynamic function calls possible?
Reply #6 - Sep 5th, 2007, 6:44pm
 
Two things here - one, davbol is right, that way of doing things is very Java, and it's often the way you do things in Swing.  It allows you to just declare the method that you need inline (what you're doing there is creating a new implementation of the buttonAction interface and implementing the required doStuff() function inline, which is quite a bit more local than having to do it all in an externally declared class, which is why it is preferred).

While this is the "correct" way to handle these things, I still feel as if it can cause quite a bit of code bloat, and to date I've never really seen a good explanation of why it's better than using reflection - to me it still seems to be mostly just a hack (albeit an officially sanctioned one) to wedge things that don't fit into Java's preferred object model.  So just to give you the choice, here's the way I'd do it (actually, this is ripped from http://code.google.com/p/phylowidget/ - Phylowidget, a Google Summer of Code project that my brother worked on).

Within your button class definition, add the following:
Code:

Object o;
Method m;

public void setAction(Object object, String method){
this.o = object;
if (method != null && !method.equals("") && o != null){
try{
m = o.getClass().getMethod(method, null);
} catch (SecurityException e){
e.printStackTrace();
} catch (NoSuchMethodException e){
e.printStackTrace();
}
}
}

public void performAction(){
if (m == null || o == null) return;
try{
m.invoke(o, null);
} catch (Exception e){
e.printStackTrace();
}
}

Then when you want to register a method to call with a button, you'd just call myButton.setAction(myObject,"doStuff"); (you might do this from within the constructor, in which case setAction does not even need to be public if you never want to change it).

To initiate the action, you'd call myButton.performAction(), probably from whatever code in the Button class you have that decides that the button has been clicked.

Lastly, if you need to access a method that is not declared within a class (i.e. at the top level in the Processing editor), then as long as you're doing so outside of other class definitions, you should be able to call myButton.setAction(this,"desiredMethodName"), which should pass the PApplet as the object, which will include the top level methods that you've declared.  If you are inside another class, you may need to store a PApplet variable that you set equal to this in the top level, and then pass that.  I haven't verified this, but I'm pretty sure it should work.

If you need to call methods with arguments, I'd take a look through Processing's PApplet.java, at http://dev.processing.org/source/index.cgi/trunk/processing/core/src/processing/core/PApplet.java?view=markup (search for "class RegisteredMethods" to get to the right piece of the file) and see the way it's done there.

For more info, check out http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html for the Javadoc on the Class class (you'll mainly be interested in the getMethod() function, and perhaps also look at the Method class), and browse a bit to see what else you may be able to use.
Re: are dynamic function calls possible?
Reply #7 - Sep 7th, 2007, 11:47pm
 
Thanks for the options guys.  I still think I'll go with reflection simply to make things easier to use for the person using the library.  Ultimately I prefer methods for doing things which don't require a ton of extra initialization, but thats just me. Everyone has their own styles.
Page Index Toggle Pages: 1