I have a simple Screen
class in C# that has a bunch of events (with corresponding delegates) like the 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:
if (someVar == someVal) {
this.FadeOutComplete += () => {
this.ShowScreen(new SomeScreen());
};
} els开发者_Python百科e {
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 must implement the interface, and I can't change the code called later.
In C#, it's common that you have code that:
- 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 can solve 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.
Is there a way to do this without inner/anonymous classes?
Edit: I just saw this SO question, which might help.
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:
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.
With lambdas in JDK 1.8 / Java 8:
private Runnable delegate;
public void delegateTest() {
// ...
this.addActionListener(e -> delegate.run());
// ...
if (someVar == someVal) {
this.delegate = () -> showSomeScreen();
}
else {
// or like this:
this.delegate = this::showSomeOtherScreen;
}
}
private void showSomeOtherScreen() {
}
private void showSomeScreen() {
}
精彩评论