The correct way to pass a function as a string

Please let me explain what I'm trying to do - I think the headline explains it something like this, but I'm not sure I'm going to do it right, so please correct me if I'm wrong!

I created a custom dialog using a LayeredPane . Essentially, a jPanel maps to POPUP_LAYER , so it appears on top of the main content. This panel contains a simple group of controls, "label-textbox-okay-cancel". I will call it the "Dialog Panel".

What I'm trying to do: When I click a button in the main window (contained in LayeredPane ) a dialog box will appear and allow the user to enter text, then click "OK" or cancel. This is all quite simple, but I would like this code to be reused, which means that other buttons in the main window will bring up the same dialog box, but with different text in the shortcut.

This, of course, requires that I turn on some kind of callback function, so that the ok button on the dialog panel launches the correct code according to the button that called it.

My current attempt is to save a string that will contain the name of the function that should be run when the user clicks the OK button on the dialog bar. I am trying to recover this string and convert it to a function name, and so far I have found many references to Reflection, many of which suggest that this is not a good idea.

In any case, I was unable to get any sample code to work, because I do not understand that "obj" is in the code below, and I am unable to call the method:

 method = obj.getClass().getMethod(myCallbackString); 

My questions:

First, am I even going to do it right? I am more than open to suggestions, but please try to keep it as simple as possible, because I'm really starting!

Secondly, what is “obj” in the above code? I would really like to know, even if it’s not how I should do something!

My other thoughts include: Should my dialog bar be in its class, and if so, how do I pass the callback function?

Any help or advice would be greatly appreciated.

By the way: In response to the question "why not use the usual dialogue?" I can only say that I'm experimenting now, and I just want to see if I can do it!

MVK

+4
source share
5 answers

obj denotes the object whose method you want to call, in your case, you can probably replace it with this (or completely exclude it, as this implied):

 private void callByName(String name) { try { getClass().getMethod(name).invoke(this); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } 

To do this, you need to declare a public no-arg method with the appropriate name.

+2
source

The usual way that callback functions are passed in Java programs is by passing instances of interfaces that implement a particular callback function. To implement the interface anonymously, however, is not required.

For example, here is the interface:

 interface MyCallback { void performCallback(); } 

Here's how you define your dialog method that performs the callback:

 void openWithCallback(MyCallback cb) { // Do something useful... ... // Perform the callback cb.performCallback(); } 

Here is the way you call this method:

 public void OpenDialog() { myDialog.openWithCallback(new MyCallback() { public void performCallback() { System.out.println("Inside callback..."); } }); } 
+5
source
  • I think your idea is correct, although it has a major drawback: you store the names of the methods as simple strings in your code, so the compiler cannot verify their validity. Therefore, if you change the name of the method, you need to manually update all the lines that reference it. This is what “reflection is a bad idea” usually means.
  • obj in your code is the object you want to call the method on. As a simple example, the equivalent of someInteger.toString(); with reflection it will be someInteger.getClass().getMethod("toString").invoke(); .

In a more general note, as soon as you feel comfortable with Java, you can also test a functional language, for example Scala, where functions are ordinary objects, and the script that you intend can be implemented with a full compiler check.

+2
source

I think you are making this path more difficult than it should be. You said you want this:

 This is all easy enough, but I would like this code to be re-usable, which means that other buttons on the main window will invoke the same Dialog Panel, but with different text in the label. 

A DialogBox is, by definition, reusable. Why don't you just listen to the click of a button when you click on the appropriate text in the dialog box so that it displays the correct information?

If you need to perform certain actions after clicking a button in a dialog box depending on the caller, you might think:

  • Created a custom extension DialogBox, which includes logic that knows what to do based on who named it. Then, when the button calls up a special dialog, it will give it a parameter to tell him what he wants to do after rejecting the dialog box.

  • Look at using something like an abstract factory pattern.

Yes, you could do it through reflection. Yes, it would be a very bad idea for many reasons that other people discussed in other answers, especially if it's production code (although you seem to point out this experiment.)

If you really want to see how to work with reflection, you probably want to read this topic. I found this one to become one of the best tutorials.

+2
source

I did not work with JPanel, but what I understand forms your request, the answer seems pretty simple. Instead of passing a method name, why don't you work with an interface and do different implementations of this interface?

+1
source

All Articles