Is it possible to polymorphically pass a function to an object array in Java?
I'm trying to create an event-based system, and interfaces simply isn't as versatile as I would like it to be.
As a result, I would like to be able to pass any function to the event manager, and have it execute the function on next iteration.
I would like to be able to pass any function to the event manager
Wouldn't we all. Unfortunately, Java doesn't have first-class functions or even function pointers. So we're stuck with interfaces and anonymous classes, until Java 8 at least.
Why not have your event manager execute Runnables, and wrap your method call with one? (This is the approach Swing took.)
public class Foo {
public void doSomething(){
System.out.println("Hello");
}
}
EventQueue.doLater(new Runnable(){
public void run(){
new Foo().doSomething();
}
}
I'm not sure why Interfaces aren't versatile enough for you - you can do anything you like with interfaces, certainly as much as you could do with passing pure functions.
Typically you would just define a single event handler interface:
public interface EventHandler {
public ReturnType handle(ParamType param);
}
Then you could implement that interface with any number of different handler classes. The handler objects can even contain their own state if that is useful.
Anything you define that implements the interface can then be used polymorphically, e.g. stored in an array so that they can be called in response to a specific event..
Java doesn't support first-class functions.
But you can do almost that by using anonymous classes or using EventHandler class.
This is from Java Docs.
The simplest use of EventHandler is to install a listener that calls a method on the target object with no arguments. In the following example we create an ActionListener that invokes the toFront method on an instance of javax.swing.JFrame.
myButton.addActionListener(
(ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
When myButton is pressed, the statement frame.toFront() will be executed. One could get the same effect, with some additional compile-time type safety, by defining a new implementation of the ActionListener interface and adding an instance of it to the button:
//Equivalent code using an inner class instead of EventHandler.
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.toFront();
}
});
Related
This question already has answers here:
Java8 Lambdas vs Anonymous classes
(9 answers)
Closed 3 years ago.
I have a button and I want a text to be displayed when I hover the mouse over the button.
Both of these work but can they be used interchangeably?
// First
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
System.out.println("Hello World");
}
};
button.setOnMouseEntered(eventHandler);
// Second. Lambda expression.
button.setOnMouseEntered(e -> {
System.out.println("Hello ");
});
I don't quite understand the first one. I suppose that EventHandler<MouseEvent> is the type and eventHandler is the name of the object. Right?
Yes, they both will execute the same code.
The first one is an so-called anonymous class. This means that you override the methods (handle in this case) of the inherited interface directly without having to do that with additional classes/interfaces.
You then pass the handler instance to the setOnMouseEntered method.
The lambda expression does this also but since the method requires a certain object type, you can write it shorter with the lambda expression.
e is basically the same as eventHandler
The first one is an anonymous inner class, where the handle method is overridden. This was the way to do listeners and handlers before lambda expressions. Now, if the class is an functional interface (only 1 abstract method, like the EventHandler in your case with its only method, handle) then a lambda expression can be used instead of anonim class.
The two methods are indeed the same, but using lambdas are preferred, because the code will be much more compact and easier to understand.
Both of the answers already provided are good, but I wanted to add another consideration.
Whenever possible, lambdas are preferable, not only because they're easier to read, but they also result in very different bytecode when compiled.
In the first example, the compiler creates a separate class (for example: OuterClass$1). This class has to be instantiated on each invocation, which will have to be garbage collected at some point.
In the second example, the lambda is compiled to a method that's local to the containing class. This means that it's a just a simple method invocation.
Depending on how frequently it's invoked, this may be an important consideration.
I believe the first example could be explicitly written as:
private class MouseHandler implements EventHandler<MouseEvent> {
public void handle(MouseEvent e) {
System.out.println("Hello World");
}
}
button.setOnMouseEntered(new MouseHandler());
This can be reduced via the anonymous class and more by the lambda expression. My understanding is that this is only possible because EventHandler is a functional interface.
What is a functional interface in Java SKO
While i'm writing some code in intellij, it keeps popping up, says
Anonymous class can be replaced with lambda?
So what does that mean? what is lambda expression and how Anonymous class can be replaced with lambda?
Play.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
}
});
Anonymous new can be replaced with lambda ?
It's not 100% correct, Anonymous class for an interfaces having one abstract method can be replaced with lambda expression (which is called functional interface)
Since ActionListener has only one method actionPerformed(ActionEvent e) you can write it using lambda expression
Play.addActionListener((event) -> {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
});
Lambda Expressions
One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.
FunctionalInterface
A functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.
Your code can be changed to this:
Play.addActionListener((event) -> {
JPanel playscreen = new JPanel();
playscreen.setBackground(Color.WHITE);
p.add(playscreen);
});
The reason you can do this is because ActionListener is a functional interface, meaning that it has exactly one abstract method that you must implement. A lambda is able to essentially take the place of that single function and act as an implementation of that interface.
The Lambda acts like the implementation of the method actionPerformed and (event) is the argument to that method and the -> { ... } is the body of that method.
I often see people write inner classes for listeners take swing for example.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//some action
}
});
At my uni there is a lot of emphasis on designs being decoupled using design patterns such as MCV or MVP.
When would I want to use an inner class over a decoupled way of doing it?
My only guess is when objects don't need to interact? (Or laziness??)
(Student)
This is actually called an anonymous inner class. You would use it if you only need to use the class once.
It would also reduce the size of your code unless it overrides many features of course (personally I prefer anonymous classes to be small in size for readability).
This Kind of Anonymous Inner Classes are called argument-defined inner classes,and automatically instantiated as part of the method invocation.
Here in the method argument, we get an object of a class,which is the subclass of the ActionListener Interface,but the newly created class is without any name(anonymous) so we cannot create its object again after the control passes through this statement.
now in the anonymous inner class which implements ActionPerformed Interface ,we override the actionPerformed() method which is very specific to that button and then new keyword creates an object of this anonymous class and it will automatically passed as argument.
or you may also create a new class(say myListener) which extends ActionListener class and overrides its actionPerformed() method. and then create a new object of myListener and pass it to the addActionListener()method as argument.
if you use metohod 2. you can see if you have 10 buttons and each have to perform different task ,then you have to create 10 ActionPerformed implementor classes and
pass object to the addActionListener() method of these implementor classes.
It is totally foolish to use this approach to create a whole new class just for a single object.
That's why most Listener are passed as an object of anonymous inner classes.
I am trying to teach myself Java and had a question that I wasn't able to answer so far. In some of my reading online I have found two ways of using action listener that seem to do the same thing. But I am trying to figure out what is the advantage/disadvantage of one over the other.
Is it better to use anonymous class like this:
public MyClass() {
...
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//doSomething
}
});
...
}
or is it best to implement at the beginning of the class like so:
public MyClass() implements ActionListener {
...
myButton.addActionListener(this);
public void actionPerformed(ActionEvent e) {
//doSomething
}
...
}
Only if your class really is an ActionListener (is-a relationship) and will be used as an ActionListener somewhere else, it should implement ActionListener.
If it is just used internally as an ActionListener, implementing ActionListener would leak implementation details to the API of the class. Use composition in that case (has-a relationship).
This is true for other interfaces and superclasses as well.
This comes down to a style thing really. Both will perform exactly the same way in code.
The separate class will tend to keep the code inside your actual method simpler, whereas the anonymous inner class brings the code for the listener implementation within the method which can make it clearer what it is doing.
There is also the case that anonymous inner classes can access final variables in the method that creates them. You can't do that with a pre-written class (although you can pass the variables into the controller).
The separate code is re-usable - so if you have the same listener in multiple places then it is the clear winner.
If you use an anonymous class, the code becomes more readable, but you may not re-utilize it.
So, I would only use an anonymous class if it's short and I'm absolutely sure that I'll not have to use it again anywhere.
It's been a few years since I've been heavily into Java. Coming back to it I'm seeing this pattern all over the place:
ratingBar.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) {
// do work
}
});
This looks more like Functional programming to me. It's a nice pattern but how is it possible to pass a method like this? In the old days a class was a class, and once compiled there was little you could do to it.
My questions are:
Can anyone let me know what this pattern is called?
How can I write a class that can be instantiated in this way.
Are there any other useful examples of functional patterns that have made their way into Java?
What do I need to Google to read more about this?
Thanks.
This passes an anonymous class, not a method.
This is a typical pattern, not just in Swing programming, but anywhere you need (hopefully) short, "throw-away" implementations of an interface or class that doesn't need to be re-used, instead of creating a full-blown implementation.
Any class/interface can be instantiated like this, there's nothing special about it:
public interface Foo {
String foo();
}
...
public class Main {
public static void main(String[] args) {
System.out.println(new Foo() {
public String foo() {
return "plugh";
}
});
}
}
Anonymous inner classes get their own class files, too, even though their source is embedded.
In this example, a Main$1.class file will be generated for the anonymous inner class, in addition to the expected Main.class file.
The statement: new OnRatingBarChangeListener() creates a new instance of a class. The following part inside the curly braces is the definition of the class.
In this case that class in an anonymous class that implements the named interface.
Anonymous classes are classes, that are declared without a name, and thus, can not be used like regular named classes.
This pattern is very common when using listeners, that often contain only a single to a few methods that do an almost trivial task.
This is the Listener pattern. Rating bar takes an implementation of OnRatingBarChangeListener and calls its onRatingChanged method on the appropriate event.
You can use instance of any class which implements OnRatingBarChangeListener. So you can use either a named class of your own or you can pass it an anonymous class like in the example. The anonymous class in the example is effectively a unnamed class which extends Object and implements OnRatingBarChangeListener. Since the class isn't named it cannot be referenced and so the instance passed is the only instance existing.
This is called "Observer pattern". A good example for this is adding action listeners for java button or other component. For example,
myButton.addActionListener(
new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//Work here
}
});
In here "myButton" is the subject and ActionListener is the observer.