2012-06-05 20 views
11

Tôi muốn tạo một lớp Java theo quy tắc định cư Scala/getters.Scala getters và setters trong lớp Java

tôi đã cố gắng sau lớp đơn giản, nhưng nó không hoạt động:

public class JavaA { 
private int a = 0; 

public int a() { 
    return a; 
} 

public void a_$eq(int a) { 
    this.a = a; 
} 
} 

Nhưng khi tôi cố gắng để truy cập nó từ scala:

val x = new JavaA 
x.a = 1 

và tôi nhận được "thuyên chuyển qua val" thông báo lỗi . Tôi đã cố gắng tìm kiếm điều này, nhưng tất cả các vấn đề tôi tìm thấy nơi cách khác từ scala sang java.

Cách phù hợp để làm điều đó là gì?

Cảm ơn!

+0

Tôi đang làm việc rất nhiều với EMF (model2model, chuyển đổi mô hình 2text) vì vậy tôi nghĩ tôi sẽ làm cho mã này thanh lịch hơn một chút với feature = value thay vì setFeatute (value). – fikovnik

Trả lời

13
Bạn chỉ có thể làm điều này, và nó đủ khó mà bạn có thể không muốn.

Những gì bạn không thể làm là viết một lớp Java trống mà được giải thích một cách kỳ diệu như Getters Scala và setters. Lý do là Scala nhúng thông tin vào tệp lớp mà nó yêu cầu cho các getters và setters của nó (ví dụ: không có khối tham số hoặc một khối tham số trống - một sự phân biệt không được bảo toàn trên JVM (hoặc trong Java)).

Những gì bạn có thể làm là sử dụng Java để thực hiện một giao diện Scala định nghĩa (tức là đặc điểm):

// GetSetA.scala 
trait GetSetA { def a: Int; def a_=(a: Int): Unit } 

// JavaUsesGSA.java 
public class JavaUsesGSA implements GetSetA { 
    private int a = 0; 
    public int a() { return a; } 
    public void a_$eq(int a) { this.a = a; } 
} 

gì bạn không thể làm, ngay cả như vậy, là sử dụng lớp trực tiếp (một lần nữa bởi vì Java không thêm thông tin chú thích thích hợp cho Scala):

scala> j.a = 5 
<console>:8: error: reassignment to val 
     j.a = 5 

nhưng vì nó không thực hiện các đặc điểm thành công ly, bạn có thể sử dụng nó như mong muốn khi được nhập là đặc điểm:

scala> (j: GetSetA).a = 5 
(j: GetSetA).a: Int = 5 

Vì vậy, đây là một túi hỗn hợp. Không hoàn hảo bằng bất kỳ phương tiện nào, nhưng nó có thể đủ chức năng để giúp đỡ trong một số trường hợp.

(Một lựa chọn khác, tất nhiên, là cung cấp chuyển đổi ngầm từ lớp Java sang lớp có trình lấy/lấy tham chiếu đến các phương thức thực trên lớp Java, điều này làm việc ngay cả khi bạn không có Java kế thừa từ Scala.)

(Chỉnh sửa: Tất nhiên không có lý do quan trọng nào mà trình biên dịch phải hành động theo cách này, người ta có thể lập luận rằng diễn giải các cặp getter/setter được định nghĩa Java như thể chúng là Scala. classfile không nói rõ ràng nó là từ Scala) là một ứng cử viên tốt cho một tính năng nâng cao để cải thiện khả năng tương tác Java.)

+0

Cảm ơn thông tin chi tiết! Tôi đã lo lắng rằng nó sẽ không hoạt động. – fikovnik

+0

Đẹp; thủ thuật tuyệt vời với đặc điểm được triển khai! –

1

Tôi sợ bạn không thể. Trong Scala, người truy cập phải là phương thức không có danh sách tham số, như def a = _a. Viết ví dụ def a() = _a trong Scala sẽ gây ra lỗi tương tự và không có cách nào để bạn có thể xác định phương thức không có danh sách tham số trong Java. Bạn có thể đánh lừa trình biên dịch Scala bằng cách tạo ra ScalaSignature của riêng bạn, nhưng điều đó có lẽ không đáng để giải quyết rắc rối…

+1

Vấn đề không phải là người truy cập. 'println (x.a)' hoạt động tốt (cũng như 'x.a _ = (1)'). –

+1

@TravisBrown Đó là vì đường cú pháp chỉ hoạt động nếu có một accessor như vậy, theo đặc tả ngôn ngữ. –

+0

Ah! Bạn đúng. Lạ thật. –