libro - programacion en java desde cero pdf
¿Es posible utilizar referencias de métodos de estilo Java 8 en Scala? (2)
Estoy desarrollando una aplicación JavaFX8 en Scala, pero no pude averiguar cómo pasar una referencia de método a un controlador de eventos. Para aclarar, no estoy usando la biblioteca ScalaFX, sino que construyo mi aplicación directamente sobre JavaFX.
Aquí está el fragmento de código relacionado.
InputController.java (escribí esta clase de prueba en Java para aislar el problema y consumir solo una referencia de método)
public class InputController {
public void handleFileSelection(ActionEvent actionEvent){
//event handling code
}
public InputController() {
//init controller
}
}
Esto funciona (Java)
InputController inputController = new InputController();
fileButton.setOnAction(inputController::handleFileSelection);
Esto no funciona (Scala)
val inputController = new InputController
fileButton.setOnAction(inputController::handleFileSelection)
Aquí está el mensaje de error del compilador (Scala 2.11.6).
Error:(125, 45) missing arguments for method handleFileSelection in class Main;
follow this method with ''_'' if you want to treat it as a partially applied function
fileButton.setOnAction(inputController::handleFileSelection)
^
Si utilizo Scala 2.12.0-M2 en su lugar, recibo un mensaje de error diferente.
Error:(125, 45) missing argument list for method handleFileSelection in class Main
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `handleFileSelection _` or `handleFileSelection(_)` instead of `handleFileSelection`.
fileButton.setOnAction(inputController::handleFileSelection)
^
¿Hay una forma nativa en la que Scala puede aprovechar las referencias de métodos introducidas en Java 8? Soy consciente del enfoque de conversiones implícitas para usar una expresión lambda, pero quiero saber si hay una forma de usar una referencia de método similar a Java 8 sin la necesidad de utilizar la declinación lambda.
Debería pasar la función que aplicando un parámetro del tipo ActionEvent
:
val button = new Button()
val inputController = new InputController()
def handler(h: (ActionEvent => Unit)): EventHandler[ActionEvent] =
new EventHandler[ActionEvent] {
override def handle(event: ActionEvent): Unit = h(event)
}
button.setOnAction(handler(inputController.handleFileSelection))
inputController::handleFileSelection
es la sintaxis de Java, que no se admite ni necesita en Scala porque ya tenía una breve sintaxis para lambdas como esta: inputController.handleFileSelection _
o inputController.handleFileSelection(_)
( inputController.handleFileSelection
también puede funcionar, dependiendo de el contexto).
Sin embargo, en Java puede utilizar lambdas y referencias de métodos cuando se espera cualquier interfaz SAM (método abstracto único), y EventHandler
es simplemente una de esas interfaces. En Scala, antes de la versión 2.11, esto no está permitido, en 2.11 hay soporte experimental para usar lambdas con interfaces SAM, que debe habilitarse usando -Xexperimental
scalac flag, y a partir de 2.12 es totalmente compatible y no necesita para ser habilitado