Reputation: 10163
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());
};
} 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 must implement the interface, and I can't change the code called later.
In C#, it's common that you have code that:
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.
Upvotes: 4
Views: 13275
Reputation: 13953
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() {
}
Upvotes: 1
Reputation: 691943
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.
Upvotes: 13