2015-08-10 31 views
16

Tôi đang phát triển một ứng dụng JavaFX8 trong Scala nhưng tôi không thể tìm ra cách chuyển một tham chiếu phương thức tới một trình xử lý sự kiện. Để làm rõ, tôi không sử dụng thư viện ScalaFX nhưng xây dựng ứng dụng của tôi trực tiếp trên đầu trang của JavaFX.Có thể sử dụng tham chiếu phương thức kiểu Java 8 trong Scala không?

Đây là đoạn mã liên quan.

InputController.java (tôi đã viết lớp thử nghiệm này trong Java để cô lập các vấn đề tiêu thụ một tài liệu tham khảo phương pháp duy nhất)

public class InputController { 
    public void handleFileSelection(ActionEvent actionEvent){ 
     //event handling code 
    } 

    public InputController() { 
     //init controller 
    } 
} 

này hoạt động (Java)

InputController inputController = new InputController(); 
fileButton.setOnAction(inputController::handleFileSelection); 

Điều này không hoạt động (Scala)

val inputController = new InputController 
fileButton.setOnAction(inputController::handleFileSelection) 

Đây là thông báo lỗi từ trình biên dịch (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) 
              ^

Nếu tôi sử dụng Scala 2.12.0-M2 thay vào đó, tôi nhận được thông báo lỗi khác.

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) 
              ^

Có cách nào để Scala có thể tận dụng các tham chiếu phương pháp được giới thiệu trong Java 8 không? Tôi biết về cách tiếp cận chuyển đổi tiềm ẩn để sử dụng một biểu thức lambda nhưng tôi muốn biết nếu có một cách để sử dụng một tham chiếu phương thức tương tự như Java 8 mà không cần sử dụng giải mã lambda.

+0

Lưu ý: Java không có tham chiếu phương thức. Bạn có thể có một đối tượng có một phương thức gọi phương thức khác (đó là những gì lambdas thực sự làm) –

+0

Tôi nghĩ rằng tôi đang nhầm lẫn với bình luận của bạn "Java không có tham chiếu phương thức". Tôi nghĩ rằng những gì tôi đang cố gắng làm là không có gì khác hơn so với ví dụ CompareProvider trong tài liệu chính thức (liên kết: https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html). – Mustafa

+0

Câu hỏi này về cơ bản là một bản sao của http://stackoverflow.com/questions/24369449/ trong ngắn hạn, bạn có thể tạo một chuyển đổi ngầm từ (T) => Đơn vị thành EventHandler [T] và nhập khẩu ngầm định. –

Trả lời

12

inputController::handleFileSelection là Java cú pháp, mà không được hỗ trợ hoặc cần thiết trong Scala vì nó đã có một cú pháp ngắn cho lambdas như thế này: inputController.handleFileSelection _ hoặc inputController.handleFileSelection(_) (inputController.handleFileSelection cũng có thể hoạt động, tùy thuộc vào ngữ cảnh). Tuy nhiên, trong Java, bạn có thể sử dụng tham chiếu lambdas và phương thức khi bất kỳ giao diện SAM (phương pháp trừu tượng đơn lẻ) nào được mong đợi và EventHandler chỉ là một giao diện như vậy. Trong Scala trước phiên bản 2.11, điều này hoàn toàn không được phép, trong 2.11 có hỗ trợ thử nghiệm để sử dụng lambdas với giao diện SAM, được bật bằng cờ scalac -Xexperimental và bắt đầu từ 2.12 nó được hỗ trợ đầy đủ và không cần được kích hoạt.

+0

Khi tôi bật các tính năng thử nghiệm, 'fileButton.setOnAction (inputController.handleFileSelection)' biên dịch không có lỗi. Tuy nhiên, thay vì được thông qua như là một tham chiếu 'handleFileSelection' phương pháp được thực hiện ngay lập tức khi dòng này được thực hiện. Tôi đoán đó là lý do tại sao nó vẫn là một tính năng thử nghiệm. – Mustafa

+0

những gì làm việc cho tôi là cho phép các tính năng thử nghiệm và để cho biểu thức lambda xử lý tham chiếu phương thức như sau. 'fileButton.setOnAction ((sự kiện: ActionEvent) => inputController.handleFileSelection)'. – Mustafa

+0

Bạn có nghĩa là '(sự kiện: ActionEvent) => inputController.handleFileSelection (sự kiện)'? Phiên bản trong nhận xét của bạn thực sự không hoạt động. –

3

Bạn nên vượt qua chức năng mà áp dụng một tham số kiểu 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)) 
+0

Thật không may, điều này không có tác dụng. 'tìm thấy: Đơn vị yêu cầu: javafx.event.EventHandler [javafx.event.ActionEvent]' Tôi có thể làm cho nó hoạt động bằng cách thay đổi chữ ký phương thức thành 'public EventHandler handleFileSelection() {' nhưng điều đó bất chấp toàn bộ mục đích của sử dụng tham chiếu phương thức. – Mustafa

+0

@Mustafa tại sao bạn không thử chỉ cần vượt qua 'inputController'? Dường như việc triển khai giao diện đích, phải không? –

+0

@Mustafa nếu bạn muốn sử dụng tham chiếu phương pháp, chúng ta nên nói về một số chức năng (người tiêu dùng, nhà cung cấp, v.v.) mong đợi 'fileButton.setOnAction' là gì? –

Các vấn đề liên quan