Java 相当于 C# 的委托/事件:动态更改事件调用代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7622992/
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-10-30 20:44:41  来源:igfitidea点击:

Java Equivalent to C#'s Delegates/Events: Changing Event Invoked Code Dynamically

c#javaevent-handling

提问by ashes999

I have a simple Screenclass in C# that has a bunch of events (with corresponding delegates) like the FadeOutEvent.

Screen在 C# 中有一个简单的类,它有一堆事件(带有相应的委托),例如FadeOutEvent.

I want to port my library to Java, and I find that the mechanism for events/delegates is really cludgey. Specifically, I cannot easily write code like:

我想将我的库移植到 Java,我发现事件/委托的机制真的很笨拙。具体来说,我不能轻易编写如下代码:

if (someVar == someVal) {
  this.FadeOutComplete += () => {
    this.ShowScreen(new SomeScreen());
  };
} else {
  this.FadeOutComplete += () => {
    this.ShowScreen(new SomeOtherScreen());
  };
}

For all you Java-only guys, essentially, what I'm whinging about is the inability to reassign the event-handling method in the current class to something else dynamically, without creating new classes; it seems that if I use interfaces, the current class mustimplement the interface, and I can't change the code called later.

对于所有只使用 Java 的人,本质上,我抱怨的是无法将当前类中的事件处理方法动态地重新分配给其他东西,而无需创建新类;好像我用接口的话,当前类必须实现接口,后面调用的代码我改不了。

In C#, it's common that you have code that:

在 C# 中,您的代码很常见:

  • In a constructor / early on, assign some event handler code to an event
  • Later during execution, remove that code completely
  • Often, change that original handler to different handler code
  • 在构造函数/早期,为事件分配一些事件处理程序代码
  • 稍后在执行期间,完全删除该代码
  • 通常,将原始处理程序更改为不同的处理程序代码

Strategy pattern cansolve this (and does), albeit that I need extra classes and interfaces to do it; in C#, it's just a delcarative event/delegate and I'm done.

策略模式可以解决这个问题(并且确实如此),尽管我需要额外的类和接口来做到这一点;在 C# 中,它只是一个 declarative 事件/委托,我完成了。

Is there a way to do this without inner/anonymous classes?

有没有办法在没有内部/匿名类的情况下做到这一点?

Edit:I just saw this SO question, which might help.

编辑:我刚刚看到这个 SO question,这可能会有所帮助。

回答by JB Nizet

Most of the time, it's done the other way round:

大多数情况下,它是反过来的:

this.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (someVar == someVal) {
            showSomeScreen();
        }
        else {
            showSomeOtherScreen();
        }
    }
});

But you could do something similar to your C# code by delegating to two other objects:

但是你可以通过委托给另外两个对象来做一些类似于你的 C# 代码的事情:

private Runnable delegate;

// ...
this.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        delegate.run();
    }
});

// ...
if (someVar == someVal) {
    this.delegate = new Runnable() {
        @Override
        public void run() {
            showSomeScreen();
        }
    };
}
else {
    this.delegate = new Runnable() {
        @Override
        public void run() {
            showSomeOtherScreen();
        }
    };
}

Delegates were proposed by Microsoft for Java a long long time ago, and were refused by Sun. I don't remember if anonymous inner classes already existed at that time or if they were chosen as the alternative.

微软早在很久以前就为 Java 提出了委托,但被 Sun 拒绝了。我不记得当时匿名内部类是否已经存在,或者它们是否被选为替代品。