简体   繁体   中英

Delegate method calling in Java

In Java: What is the best way to pass a method from one object to another so that it can be called at a later time by the second object?

I come from an ActionScript background where it is as easy to pass around references to methods as it is to pass around references to variables but this seems to be much more difficult in Java. The first few links I found flat out say it is not possible (and it may have been at the time of their posting), but then I found http://www.javacamp.org/javavscsharp/delegate.html which details how this can be accomplished.

My issue with using Javacamp's example is the string based reference to the method. Methods get renamed all the time and a string reference will only complain once you actually run that function runtime as opposed to compile time for a proper explicit link.

Is there no way to do this with proper explicit links to the method you want the other class to execute?

Model of what I am hoping to accomplish:

  1. Player clicks an upgrade button on Activity1 > Activity1 passes upgrade method to a new confirmation activity
  2. Player clicks "Yes" > Confirmation activity calls upgrade method passed in from Activity1
  3. OR: Player clicks "No" > Confirmation Activity closes

EDIT: To be clear I am not looking for a static method solution as that would require my Confirmation activity to hold many lines of logic for which static method to call. The Confirmation activity will be used all over my application: a simple "Are you sure you want to X?" -Yes -No, if yes execute X

I am currently looking at implementing onActivityResult to avoid this issue but that will be more logic than I like for this kind of issue.

you can use interfaces like this:

public interface MyMethod {
    public void method();
}


public class FirtObject{

    private SecondObject ob;

    public void tellSecondObjectExecuteLater(){
        ob.executeLater( new MyMethod() { 
          public void method(){System.out.println("duh Method");} });
    }
}

public class SecondObject {

    private MyMethod myMth;

    public void executeLater(MyMethod mth){
        myMth = mth;
    }

    public void executeNow(){
        myMth.method();
    }
}

does this solve your problem?

The typical way to pass methods is to use an Interface and Anonymous Inner Classes. In order to maintain static typing an Interface is used to declare the method signature and typing information. The caller can use either a concrete implementation of that interface as a normal class or using Anonymous Inner Classes for quick class creation. I'll use standard Java SDK classes to illustrate:

interface Comparator<T> {
    public int compare( T a, T b); 
}

class SpecialCollection<T> {
    public void sort( Comparator<T> comparator ) {...} 
}

public class SomeClient {
    public void doSomething( SpecialCollection<SpecialObj> collection ) {

        collection.sort( new Comparator<SpecialObj>() {
           public int compare( SpecialObject a, SpecialObject b ) {
               // some implementation
           }
        } );
    }
}

The above is an example of a strategy pattern. The thing about the strategy pattern (and passing callback methods like in Javascript). The author has to plan for those types of extensions. The author has to predict up front where he/she wants you to extend. And it just happens it's cleanest if you use Interfaces.

However, pure delegation doesn't have to have always involve Interfaces. You can pass concrete classes, since Java can always pass a subclass that overrides various methods of that class to change what method or code will be invoked. For example in Java InputStream/OutputStream are abstract classes and you typically pass subclass instances to the methods.

If you need the method to act differently depending on the context (AKA, it is different depending on how it is created), you'll want to pass along the instance of the class that the method is in.

If it is a static method, you can just referenced the method itself if you import that class at the top of your new class.

For example, lets say you have a method that will tell you stuff about a certain string. IF the class looks like this:

class stringChecker {
    private String stringToCheck;
    public class stringChecker(String s) {
         stringToCheck = s;
    }
    public int getStringLength() {
         return stringToCheck.length();
    }
    public boolean stringStartsWith(String startsWith) {
         return (stringToCheck.indexOf(startsWith) == 0);
    }
}

Then you'll want to pass along the instance, since it is non-static. Different instances have different strings that they were created with, so you will get a different return if you use a different instance.

However, if your class looks more like this:

class stringChecker {
     public static int getStringLength(String s) {
          return s.length();
     }
     public static boolean stringStartsWith(String s, String startsWith) {
          return (s.indexOf(startsWith) == 0);
     }
}

Then you can just reference those methods with stringChecker.getStringLength("test");, because the methods are static. It doesn't matter what instance they are in. The returned result depends ONLY on what is being passed in. You just have to make sure to add import stringChecker; at the top or whatever your class will be called. For you, it'll probably be something like com.example.blah.otherthing.stringChecker, since you're working with android.

Good luck! I hope this helps :)

EDIT: Looks like I may have read the problem too quickly...if this isn't what you were asking about, just let me know with a comment and I'll delete this answer so as to not confuse anybody else.

You said that you are using it in a project to open a Confirmation activity.

Activities should not contain references to each other to avoid memory leaks. To pass data between activities should be used Intent class. To receive a result, call StartActivityForResult() and get result in the onActivityResult() method.

But in general for your task is more suitable AlertDialog or PopupWindow .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM