Should I try to call a method dynamically?

edited May 2016 in Questions about Code

Hi All,

in a little program I'm trying to write, I would like each character of a String to invoke a method specific to that character. For example, the String "ABC" would invoke, in series, methods paintA(), paintB() and paintC().

I've seen stuff about Reflection in Java, where you can actually invoke methods programmatically, i.e. invoke the method by "reading" its name from a String, but the code really confuses me... I'm not good enough to understand how this works.

Maybe you have a trick to help achieve something similar, even if less elegant?

Answers

  • Wow, why was the question posted twice? First time it threw an exception so I though it hadn't gone trhough... sorry. Can the mods please erase the duplicate?

  • edited May 2016 Answer ✓

    If a function resides at the top, along setup() & draw(), it can be invoked via method() function.

  • Very, very nice, thanks. This makes life way easier! On a different note, I quite like your technique of the hasClicked() method in the Button class!

  • edited May 2016

    Can you invoke a method using arguments in this way? Say, if the method I would like to invoke looked like paintA(float x) {stuff}? How would you write this?

  • Oh I'm just grasping your first reply: it means this wouldn't work for a class method, right?

  • Unfortunately only "free-roam" Processing functions.
    For methods inside classes demand we implement reflection. :-\"

  • edited May 2016

    Okay, groping in the dark with an implementation of Reflection with a class method here. I know it's wrong, but I don't know what actually is. Evidently this refers to the PApplet (what is a PApplet?) when it should somehow point to the word object. Can you help further?

    Word word;
    
    void setup() {
      size(640, 480, P2D);
      word = new Word("X");
    }
    
    void draw() {
      background(0);
      word.go(this);
    }
    
    class Word {
    
      private String word;
    
      Word(String t_word) {
        word = t_word;
      }
    
      public void paintX() {
        pushMatrix();
        translate(width/2, height/2);
        line(0, 0, 20, 20);
        line(0, 20, 20, 0);
        popMatrix();
      }
    
      void painter(PApplet p, String method) {
        p.method(method);
      }
    
      void go(PApplet p) {
        painter(p, "paint" + word);
      }
    }
    
  • edited May 2016

    I've already told you those functions invoked by method() (and btW thread() as well) gotta be "roam" 1s.

    In your sketch above, paintX() is a method from class Word.
    And therefore, neither method() not thread() can reach that out! :-SS

    Move method paintX() outta class Word, so it belongs to the "sketch" class instead. *-:)

    P.S.: Add stroke(-1); in setup() so those line() statements can actually show up.

  • edited May 2016

    Okay thanks for your reply. I had got it the first time. It's just, I wish really I could make paintX() a method inside class Word (and thus implement Reflection like you said above). But nevermind, for what I'm intending to do, I can work around this by writing extra code. @-) Thanks!

  • edited May 2016 Answer ✓

    ... I wish really I could make paintX() a method inside class Word(and thus implement Reflection like you said above).

    You can always open a new tab on PDE and move all your "reflection" functions there.
    It's as almost as if they were in their own class methinks. :>

    Anyways, if you feel that you need those functions to belong to some class, you can't use the convenient method() anymore. You've gotta implement reflection by yourself! :(

    You can go w/ getDeclaredMethod(): http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethod-java.lang.String-java.lang.Class...-

    Or rather go w/ getMethod() as long as you declare class Word as public: public class Word {
    http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getMethod-java.lang.String-java.lang.Class...-

    Some links to help ya out if you decide for this harder approach: :ar!

    1. http://StackOverflow.com/questions/17953724/using-getdeclaredmethod-to-get-a-method-from-a-class-extending-another
    2. https://forum.Processing.org/two/discussions/tagged?Tag=getmethod()
  • Thanks for a complete and well informed reply -- like always! :-bd I'm working through the examples and posts you provided. If I get this correctly, Reflection could be seen as treating methods like objects.

  • Trying to understand the mechanics of this. What should I do so the following does not throw exception NoSuchMethod?

    Test tester;
    
    void setup() {
      tester = new Test();
    }
    
    void draw() {
      println(tester.getClass().getMethod("myMethod"));
    }
    
    class Test {
    
      Test() {
      }
    
      public void myMethod() {
      }
    }
    
  • edited May 2016

    You've got an unhandled compilation error. That means the method you're trying to invoke throwssome checked Exception. Therefore it demands some try/catch () block to deal w/ it: [-X

    1. http://docs.Oracle.com/javase/8/docs/api/java/lang/Exception.html
    2. https://Processing.org/reference/try.html

    Anyways, here's a much more detailed getMethod() + invoke() example: :>

    /**
     * Invoke Method Example (v1.2)
     * GoToLoop (2016-May-16)
     *
     * forum.Processing.org/two/discussion/16573/
     * should-i-try-to-call-a-method-dynamically
     */
    
    import java.lang.reflect.Method;
    
    class Test {
      String[] myMethod(final String msg, final double num) {
        println(msg, Math.cbrt(num));
        return platformNames;
      }
    }
    
    void setup() {
      Test tester = new Test();
    
      Method m = getMethod(Test.class, "myMethod", String.class, double.class);
      println(m);
    
      String[] result = (String[]) invokeMethod(m, tester, "Moxl", -27);
      println(result);
    
      exit();
    }
    
    static final Method getMethod(Class<?> c, String name, Class<?>... params) {
      try {
        return c.getMethod(name, params);
      }
    
      catch (NoSuchMethodException e) {
        //throw new RuntimeException(e);
        System.err.println(e);
        return null;
      }
    }
    
    static final Object invokeMethod(Method m, Object obj, Object... args) {
      try {
        return m.invoke(obj, args);
      }
    
      catch (ReflectiveOperationException e) {
        //throw new RuntimeException(e);
        System.err.println(e);
        return null;
      }
    
      catch (IllegalArgumentException e) {
        //throw new RuntimeException(e);
        System.err.println(e);
        return null;
      }
    }
    
  • This discussion might help.

  • Thanks for all the time and help, guys. I need time and practice to wrap my head around this.

Sign In or Register to comment.