0

I have a clas called as MyFunctions that defines different functions func1, func2, etc. Also I have a class Process that stores the function name assigned to the object of this class:

Process p1 = new Process();
String fName1 = "func1";
p1.setFunctionName(fName1); 
Process p2 = new Process();
String fName2 = "func2";
p2.setFunctionName(fName2); 

In order to run a proper function, I do the following:

MyFunctions f = new MyFunctions();
if (p.getFunctionName() == "func1") {
   output = f.func1(inputdata);
} else if (p.getFunctionName() == "func2") {
   output = f.func2(inputdata);
}

I´m not sure that this approach is efficient. Is there any other way to solve this task?

Another question: is it possible to do something like this in JAVA?:

String fName = p.getFunctionName();
output = f."+fName+"(input);
Klausos Klausos
  • 15,308
  • 51
  • 135
  • 217

6 Answers6

2

First, this approach is not exactly correct. Never use == to compare objects. Use equals() instead:

MyFunctions f = new MyFunctions();
if ("func1".equals(p.getFunctionName())) {
   output = f.func1(inputdata);
} else if ("func2".equals(p.getFunctionName())) {
   output = f.func2(inputdata);
}

Second, I'd suggest you to use enum instead.

public enum FunctionInvoker {
    func1 {
        public Object invoke(MyFunctions o, Object ... arg) {
             o.func1(arg[0]);
        }
    },
    func2 {
        public Object invoke(MyFunctions o, Object ... arg) {
             o.func2(arg[0], arg[1]);
        }
    },
}

Now the usage looks like:

String functionName = ...; // probably read from file, etc.
Object result = FunctionInvoker.valueOf(functionName).invoke(args);
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Object result = FunctionInvoker.valueOf(functionName).invoke(args); I changed it to ...invoke(new MyFunctions(),args); But still I cannot compile the code. It says that the method ´invoke´ is undefined. – Klausos Klausos Jan 17 '12 at 10:33
  • It started working after including: public abstract Object invoke(MyFunctions o, Object args); – Klausos Klausos Jan 17 '12 at 10:36
1

Java's Reflection API will most likely be useful to you. It allows you (among other things) to find methods in classes at runtime (when you have for example the method name in a string) and call methods that way.

A simple example:

String inputdata = "Hello";

// Finds the method "func1" in class MyFunctions that takes a String argument
Method method = MyFunctions.class.getMethod("func1", String.class);

// Calls the method on a new MyFunctions object, passing in inputdata
// as the argument
Object result = method.invoke(new MyFunctions(), inputdata);

System.out.println("Return value: " + result);
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • It says: java.lang.NoSuchMethodException: cpn_logic.MyFunctions.func1(java.lang.String) at java.lang.Class.getMethod(Unknown Source) – Klausos Klausos Jan 17 '12 at 10:15
  • @KlausosKlausos Does your class really have a method `func1` that takes a `String` argument? It was just an example of how to use the reflection API, not to be taken literally. You must adapt it for your own program. – Jesper Jan 17 '12 at 11:13
1

If you have a determined set of functions, then use public static constants to declare the names of the functions.

Example:

public static String FUNCTION1 = "func1";
public static String FUNCTION2 = "func2";

For you second question, yes it is possible using java reflection.

Adel Boutros
  • 10,205
  • 7
  • 55
  • 89
1

You can use reflection to find the function to execute.

For instance:

f.getClass().getDeclaredMethod(p.getFunctionName).invoke();
Hiery Nomus
  • 17,429
  • 2
  • 41
  • 37
1

I´m not sure that this approach is efficient. MyFunctions f = new MyFunctions(); if (p.getFunctionName() == "func1") {

No. AFAIK it will not work. You are comparing references of String instead of comparing it's content.

if (p.getFunctionName() == "func1") 

use .equals instead of == to compare 2 strings.


is it possible to do something like this in JAVA? output = f."+fName+"(input);

You can use reflection in java to do what you want.

Harry Joy
  • 58,650
  • 30
  • 162
  • 207
1

Use an enum to decouple:

public enum Function {
ONE {
public void call(Functions functions) {
functions.func1();
},
TWO {
...
};

public abstract void call(Functions functions); }

An the process:

Process p1 = new Process(Function.ONE);
MyFunctions f = new MyFunctions();
p1.call(f);

Hope you got the idea :)

Jerome L
  • 607
  • 5
  • 11