2011-10-02 31 views
5

tôi vẫn còn khá mới để Scala, nhưng tôi biết bạn có thể xác định các biến lớp được khởi tạo trong constructor nhưScala biến cuối cùng trong constructor

class AClass(aVal: String) 

đó sẽ như thế nào làm như sau trong java

class AClass { 
    private String aVal; 

    public AClass(String aVal) { 
     this.aVal = aVal; 
    } 
} 

Trong Java, tôi sẽ khai báo aVal là cuối cùng. Có cách nào để làm cho biến aVal cuối cùng trong cú pháp Scala?

EDIT: Đây là những gì tôi nhìn thấy khi tôi biên dịch lớp Scala sau:

class AClass(aVal: String) { 
    def printVal() { 
    println(aVal) 
    } 
} 

Tôi chạy javap -private và có đầu ra

public class AClass extends java.lang.Object implements scala.ScalaObject{ 
    private final java.lang.String aVal; 
    public void printVal(); 
    public AClass(java.lang.String); 
} 

Khi tôi thay đổi định nghĩa lớp scala có class AClass(**val** aVal: String) Tôi nhận được kết quả sau đây từ javap -private

public class AClass extends java.lang.Object implements scala.ScalaObject{ 
    private final java.lang.String aVal; 
    public java.lang.String aVal(); 
    public void printVal(); 
    public AClass(java.lang.String); 
} 

Phương thức công khai aVal được tạo. Tôi vẫn đang học ở đây - bất cứ ai có thể giải thích lý do tại sao nó được tạo ra?

Note Tôi đang sử dụng scala 2,9

Trả lời

10
class AClass(aVal: String) 

Trong mã này, Aval là một biến thức. Vì vậy, bạn đã có một biến cuối cùng.

class AClass(val aVal: String) 

Trong mã này, aVal là cuối cùng và bạn có getter của aVAl. Vì vậy, bạn có thể sử dụng nó như dưới đây

scala> val a= new AClass("aa") 
a: A1 = [email protected] 

scala> a.aVal 
res2: String = aa 

Và cuối cùng,

class AClass(var aVal: String) 

Trong mã này, Aval là không chính thức và bạn có getter và setter của Aval. Vì vậy, bạn có thể sử dụng nó như dưới đây

scala> val a= new AClass("aa") 
a: AClass = [email protected] 

scala> a.aVal 
res3: String = aa 

scala> a.aVal = "bb" 
a.aVal: String = bb 

scala> a.aVal 
res4: String = bb 
8

sao chép từ câu trả lời của tôi: Scala final vs val for concurrency visibility

Có hai ý nghĩa của thuật ngữ final: a) cho Scala lĩnh vực/phương pháp và phương pháp Java nó có nghĩa là "không thể overridded trong một phân lớp "và b" cho các trường Java và trong bytecode JVM nó có nghĩa là "trường phải được khởi tạo trong hàm tạo và không thể được gán lại".

Thông số lớp được đánh dấu bằng val (hoặc tương đương, tham số lớp trường hợp không có công cụ sửa đổi) thực sự là cuối cùng theo nghĩa thứ hai và do đó luồng an toàn.

Dưới đây là bằng chứng:

scala> class A(val a: Any); class B(final val b: Any); class C(var c: Any) 
defined class A 
defined class B 
defined class C 

scala> import java.lang.reflect._ 
import java.lang.reflect._ 

scala> def isFinal(cls: Class[_], fieldName: String) = { 
    | val f = cls.getDeclaredFields.find(_.getName == fieldName).get 
    | val mods = f.getModifiers 
    | Modifier.isFinal(mods) 
    | } 
isFinal: (cls: Class[_], fieldName: String)Boolean 

scala> isFinal(classOf[A], "a") 
res32: Boolean = true 

scala> isFinal(classOf[B], "b") 
res33: Boolean = true 

scala> isFinal(classOf[C], "c") 
res34: Boolean = false 

Hoặc với javap, có thể được chạy thuận tiện từ REPL:

scala> class A(val a: Any) 
defined class A 

scala> :javap -private A 
Compiled from "<console>" 
public class A extends java.lang.Object implements scala.ScalaObject{ 
    private final java.lang.Object a; 
    public java.lang.Object a(); 
    public A(java.lang.Object); 
} 

Nếu tham số lớp của một lớp không hợp cụ thể không được đánh dấu như một val hoặc var, và nó không được đề cập đến từ bất kỳ phương pháp nào, nó chỉ cần hiển thị với hàm tạo của lớp. Trình biên dịch Scala sau đó được tự do tối ưu hóa trường khỏi mã byte. Trong Scala 2.9.1, điều này dường như hoạt động:

scala> class A(a: Any) 
defined class A 

scala> :javap -private A 
Compiled from "<console>" 
public class A extends java.lang.Object implements scala.ScalaObject{ 
    public A(java.lang.Object); 
} 
+0

Ug. Tôi phải quên biên dịch lại và sau đó chứng thực các phát hiện của tôi với hành vi của các triển khai cũ hơn (http://scala-programming-language.1934581.n4.nabble.com/Val-and-Final-td1993410.html). Bạn thực sự là chính xác. Vấn đề tôi đã đề cập về các lớp con có thể ghi đè các vals (và đây là một vấn đề cho trận chung kết) bị phá vỡ bởi trường cơ bản là private và accessors trong các lớp được tạo ra sẽ ghi đè các lớp trong parent (không phải là final). Cảm ơn bạn đã đặt nó thẳng. – Chris

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