java Java中的委托方法调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25799304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:43:13  来源:igfitidea点击:

Delegate method calling in Java

javaandroid

提问by Currence

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?

在 Java 中:将方法从一个对象传递到另一个对象以便稍后可以由第二个对象调用的最佳方法是什么?

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.htmlwhich details how this can be accomplished.

我来自 ActionScript 背景,其中传递对方法的引用与传递对变量的引用一样容易,但这在 Java 中似乎要困难得多。我发现的前几个链接完全表明这是不可能的(并且可能在他们发布时已经存在),但后来我发现http://www.javacamp.org/javavscsharp/delegate.html详细说明了这是如何实现的可以实现。

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.

我使用 Javacamp 示例的问题是对该方法的基于字符串的引用。方法会一直被重命名,并且字符串引用只会在您实际运行该函数运行时才会抱怨,而不是正确显式链接的编译时间。

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
  1. 玩家点击 Activity1 上的升级按钮 > Activity1 将升级方法传递给新的确认活动
  2. 玩家点击“是”> 确认活动调用从 Activity1 传入的升级方法
  3. 或:玩家点击“否”> 确认活动关闭

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

编辑:明确地说,我不是在寻找静态方法解决方案,因为这需要我的 Confirmation 活动为要调用的静态方法保留多行逻辑。Confirmation 活动将在我的整个应用程序中使用:一个简单的“您确定要 X 吗?” -Yes -No, 如果是,执行 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.

我目前正在考虑实施 onActivityResult 以避免此问题,但这将比我喜欢的此类问题更具逻辑性。

回答by jcstar

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?

这能解决你的问题吗?

回答by chubbsondubs

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:

传递方法的典型方式是使用接口和匿名内部类。为了保持静态类型,接口用于声明方法签名和类型信息。调用者可以使用该接口的具体实现作为普通类,也可以使用匿名内部类来快速创建类。我将使用标准的 Java SDK 类来说明:

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.

以上是一个策略模式的例子。关于策略模式的事情(以及在 Javascript 中传递回调方法)。作者必须为这些类型的扩展做计划。作者必须预先预测他/她希望您扩展的位置。如果您使用接口,它恰好是最干净的。

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.

然而,纯委托不一定总是涉及接口。您可以传递具体的类,因为 Java 始终可以传递覆盖该类的各种方法的子类,以更改将调用的方法或代码。例如,在 Java 中 InputStream/OutputStream 是抽象类,您通常将子类实例传递给方法。

回答by Alex K

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.

如果您需要该方法根据上下文(AKA,它因创建方式而异)采取不同的行动,您将需要传递该方法所在的类的实例。

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.

然后您可以使用 stringChecker.getStringLength("test"); 引用这些方法,因为这些方法是静态的。它们在哪个实例中无关紧要。返回的结果仅取决于传入的内容。您只需要确保添加 import stringChecker; 在顶部或任何您的班级将被称为。对您来说,它可能类似于 com.example.blah.otherthing.stringChecker,因为您使用的是 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.

编辑:看起来我可能读得太快了……如果这不是您要问的问题,请通过评论告诉我,我将删除此答案以免混淆其他人。

回答by Dmitriy Puchkov

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 Intentclass. To receive a result, call StartActivityForResult()and get result in the onActivityResult()method.

活动不应包含对彼此的引用以避免内存泄漏。要在活动之间传递数据,应使用Intent类。要接收结果,请调用StartActivityForResult()并在onActivityResult()方法中获取结果。

But in general for your task is more suitable AlertDialogor PopupWindow.

但总的来说,对于您的任务更适合AlertDialogPopupWindow