2011-10-02 14 views
5

nadal jestem całkiem nowy, Scala, ale wiem, że można zdefiniować zmienne klasy, które są inicjowane w konstruktorze jakScala zmienne końcowe w konstruktorze

class AClass(aVal: String) 

który będzie jak w następujący sposób w Javie

class AClass { 
    private String aVal; 

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

W języku Java zadeklarowałbym aVal jako ostateczny. Czy istnieje sposób na stworzenie zmiennej zmiennej aVal w składni Scala?

EDIT: Tutaj jest to, co widzę, kiedy mogę skompilować następujące klasy Scala:

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

wpadłem javap -private, ale wyjście

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

Kiedy zmienić definicję klasy scala mieć class AClass(**val** aVal: String) Otrzymuję następujące dane wyjściowe od 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); 
} 

Generowana jest publiczna metoda aVal. Nadal się tutaj uczę - czy ktoś może wyjaśnić, dlaczego tak się dzieje?

Uwaga używam Scala 2,9

Odpowiedz

10
class AClass(aVal: String) 

W tym kodzie Aval jest zmienną ostateczna. Więc masz już ostatnią zmienną.

class AClass(val aVal: String) 

W tym kodzie aVal jest ostateczna i pobiera się wartość aVAl. Więc można go używać jak poniżej

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

scala> a.aVal 
res2: String = aa 

i wreszcie

class AClass(var aVal: String) 

W tym kodzie Aval nie jest ostateczna i masz getter i setter Aval. Więc można go używać jak poniżej

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

Skopiowane z moją odpowiedź: Scala final vs val for concurrency visibility

Istnieją dwa znaczenia terminu final: a) dla Scala Pola/metody i sposoby Java to znaczy „nie może być overridded w podklasa "i b) dla pól Java oraz w kodzie bajtowym JVM oznacza" pole musi zostać zainicjowane w konstruktorze i nie można go ponownie przypisać ".

Parametry klasy oznaczone val (lub równoważnie, parametry klasy sprawy bez modyfikatora) są rzeczywiście ostateczne w drugim znaczeniu, a zatem bezpieczne dla wątków.

Oto dowód:

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 

Albo z javap, które mogą być łatwo uruchamiane z 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); 
} 

Jeśli parametr klasa klasy non-case nie jest oznaczony jako val lub var, i nie jest przywoływany z żadnej metody, musi być widoczny tylko dla konstruktora klasy. Kompilator Scala może następnie optymalizować pole z dala od kodu bajtowego. W wersji Scala 2.9.1 wygląda na to, że działa:

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. Musiałem zapomnieć o rekompilacji, a następnie potwierdziłem moje odkrycia z zachowaniem starszych implementacji (http://scala-programming-language.1934581.n4.nabble.com/Val-and-Final-td1993410.html). Jesteś rzeczywiście poprawny. Problem, o którym wspomniałem, o tym, że podklasy są w stanie przesłonić valsy (i jest to problem dla finałów) jest obchodzony z uwagi na to, że ukryte pole jest prywatne, a akcesory w wygenerowanych klasach nadpisują te w rodzicu (które nie są ostateczne). Dzięki za ustawienie go prosto. – Chris