method

Call method by String or Reference

Sometimes you may need to call a method, but you don’t know which one in advance i.e. you want to postpone the decision to runtime.
There are two basic ways to that :

  • Store the method name as a String and build the “call” on the fly when you need it
  • Store a reference to a method in a variable and then use language specific syntax to invoke the method

For example let say you have written multiple standalone tests and you want to run different combination of them based on different needs. In other words you want to parameterize method calls.

Something along the lines :

run_tests -suite=3,5,8
run_tests -suite=2..5

If you have a few combinations you can hard code them, but it is more flexible to “pick” the tests/methods on the fly.

This is just one example of the need for selecting the function/method at the last moment. In most cases you prepare or store the name in a String.

What follows are examples of how to do this in several languages.

Python

There are many different ways to call a function or a method indirectly. Below you can see most of them.

#shortcut of : def say(*a): print(*a)
say = print

#using eval()
eval("say")("hello")
say_hi = "say('hi')"
eval(say_hi)

#call defined functon via locals
locals()["say"]('boo hoo')

#via reference stored in a dict
funs = { 'sayit' : say }
funs['sayit']('sayit')

# ----- and now ... -----

#methods in a string
class StringMethod:
  
  def say(self, *args) : print(*args)
  
  
sm = StringMethod()

#"create" a method
method = getattr(sm,"say")
method("howdy")

#direct assignment
sm_say = sm.say
sm_say('whats sup')

#unbound
sayit = StringMethod.say
sayit(sm,'bye')


-----

hello
hi
boo hoo
sayit
howdy
whats sup
bye

Java

In Java you have to use Reflection. You do it in two steps :

  • First you create a Method out of the String and a description of the parameters
  • Then you call the .invoke() method with the real values

import java.util.*;
import java.lang.reflect.*;


public class MethodReflection {

  public static <ARG> void say(ARG arg) { System.out.println(arg); }

  public void say_hi() { say("hi"); }
  private void sayit(String str) { say(str); }
  
  public void test() throws Exception {
    //get the class that hold the methods you want to call
    Class<?> klass = MethodReflection.class;//Class.forName("MethodReflection");
    
    //get a method w/o arguments
    Method m1 = klass.getMethod("say_hi");// or getDeclaredMethod()
    m1.invoke(this);
    
    //private method requires getDeclaredMethod(), also using one String argument
    Method m2 = klass.getDeclaredMethod("sayit", String.class);
    m2.invoke(this, "hello");
    
    //unknown argument
    Method m3 = klass.getMethod("say", Object.class);
    //first argument null for static method
    m3.invoke(null, "howdy");
    
  }

  public static void main(String[] args) throws Exception {
    MethodReflection mc = new MethodReflection(); 
    mc.test();
  }
}

-----

hi
hello
howdy

JavaScript

say = console.log

eval("say('hi')")

sayit = "say"
window[sayit]('sayit')

-----

hi
sayit

Python magic methods list

Binary Operators

Operator           Method
+                  obj.__add__(self, other)
-                  obj.__sub__(self, other)
*                  obj.__mul__(self, other)
//                 obj.__floordiv__(self, other)
/                  obj.__div__(self, other)
%                  obj.__mod__(self, other)
**                 obj.__pow__(self, other[, modulo])
<<                 obj.__lshift__(self, other)
>>                 obj.__rshift__(self, other)
&                  obj.__and__(self, other)
^                  obj.__xor__(self, other)
|                  obj.__or__(self, other)

Assignment Operators:

Operator          Method
+=                obj.__iadd__(self, other)
-=                obj.__isub__(self, other)
*=                obj.__imul__(self, other)
/=                obj.__idiv__(self, other)
//=               obj.__ifloordiv__(self, other)
%=                obj.__imod__(self, other)
**=               obj.__ipow__(self, other[, modulo])
<<=               obj.__ilshift__(self, other)
>>=               obj.__irshift__(self, other)
&=                obj.__iand__(self, other)
^=                obj.__ixor__(self, other)
|=                obj.__ior__(self, other)

Unary Operators:

Operator          Method
-                 obj.__neg__(self)
+                 obj.__pos__(self)
abs()             obj.__abs__(self)
~                 obj.__invert__(self)
complex()         obj.__complex__(self)
int()             obj.__int__(self)
long()            obj.__long__(self)
float()           obj.__float__(self)
oct()             obj.__oct__(self)
hex()             obj.__hex__(self)

Comparison Operators

Operator          Method
<                 obj.__lt__(self, other)
<=                obj.__le__(self, other)
==                obj.__eq__(self, other)
!=                obj.__ne__(self, other)
>=                obj.__ge__(self, other)
>                 obj.__gt__(self, other)