2010-07-13 44 views
6

Cố gắng thực hiện các mã tương tự như tìm thấy trong ví dụ bậc-chức năng cao hơn từ http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6Scala ActionListener/loại chức năng ẩn danh không phù hợp

val button = new JButton("test") 
button.addActionListener{ e:ActionEvent => println("test") } 
add(button) 

dẫn đến những điều sau

error: type mismatch; 
found : (java.awt.event.ActionEvent) => Unit 
required: java.awt.event.ActionListener 
    button.addActionListener{ e:ActionEvent => println("test") } 
             ^

Điều này đúng ở ít nhất là với trình biên dịch Scala phiên bản 2.7.6.final trên hệ thống của tôi. Tôi có thể đạt được những gì tôi muốn theo cách thức kiểu Java của việc triển khai một cách rõ ràng một ActionListener ẩn danh.

button.addActionListener(new ActionListener() { 
    def actionPerformed(e:ActionEvent) { println("test") } 
}) 

Theo tôi hiểu, Scala sẽ có thể sử dụng kiểu gõ vịt để hiển thị việc triển khai ActionListener rõ ràng không cần thiết; vậy tại sao nó không hoạt động ở đây? Tôi đã không có kinh nghiệm thực tế của vịt gõ vào thời điểm này.

Trả lời

11

Nhập liệu không có gì liên quan đến lý do mã của bạn không hoạt động. Đó là vì hệ thống kiểu của Scala không cung cấp chuyển đổi ngầm định giữa loại giao diện và loại chức năng theo mặc định. Tuy nhiên, nếu chuyển đổi ngầm định sau được xác định, mã của bạn hoạt động chính xác.

implicit def toActionListener(f: ActionEvent => Unit) = new ActionListener { 
    def actionPerformed(e: ActionEvent) { f(e) } 
} 

Chuyển đổi tiềm ẩn này cung cấp chuyển đổi từ (ActionEvent => Unit) sang ActionListner.

+1

Không phải là chủ nghĩa cuồng tín, nhưng đáng chú ý là cả Groovy và các đề xuất đóng cửa Java khác nhau đều bao gồm các chuyển đổi ngầm từ các kiểu hàm thích hợp sang các giao diện phương thức đơn. Điều này rất thuận tiện cho các giao diện như Runnable hoặc Comparable. Trong Scala, bạn cần phải thực hiện chuyển đổi này bằng tay, hoặc dựa vào các thư viện pimped để thực hiện nó. –

+1

@Dave Có ... nếu loại không khớp, hãy tự động truyền. Tôi nghĩ rõ ràng là tại sao Scala không chọn cách này. –

+0

Ồ, chắc chắn rồi. Nó chỉ có ý nghĩa đối với Groovy và Java vì chúng không bao gồm bất kỳ cách nào tốt để mở rộng các thư viện hiện có, vì vậy chúng cần chuyển đổi tự động này để làm việc với Java kế thừa không đau đớn. Scala có các thư viện cho các thư viện cũ, và các thư viện mới nên được (và đang được) viết để ủng hộ các biểu mẫu chức năng trên các giao diện một phương thức. –

4

Scala không phải là loại vịt. Nó có tùy chọn, cấu trúc rõ ràng-gõ, nhưng điều đó không có bất cứ điều gì để làm với lý do tại sao mã của bạn không hoạt động.

Mã của bạn không hoạt động, bởi vì JButton.addActionListener mong đợi một đối số của nó là ActionListener chứ không phải hàm. Ngay cả khi scala được ducktyped, bạn không thể chỉ vượt qua một chức năng bởi vì các phương pháp tương tự có sẵn trên một ActionListener không có sẵn trên một chức năng. Lưu ý rằng bài viết nói "Hãy giả sử trong một khoảnh khắc vui vẻ mà chúng tôi có thể viết lại Swing để tận dụng cú pháp của Scala", tức là bài viết không yêu cầu hiển thị cho bạn mã thực sự hoạt động.

Tuy nhiên scala không có gói xoay của riêng nó (scala.swing) có chứa các lớp có nhiều "scalaish" để sử dụng hơn tương đương java của chúng.

+0

Ah, trích dẫn đó từ bài viết thực sự là thích hợp. Tôi có cảm giác đặt câu hỏi trước công chúng bị ràng buộc để lộ một số lỗi đọc hiểu cơ bản về phía tôi ... Tuy nhiên, câu trả lời của bạn là thông tin. Cảm ơn. – PeterT

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