2013-05-08 11 views
7

Gram z Scalą. I znalazłem 3 ciekawe rzeczy (tytuł jest trzeci).Dlaczego kompilator Scala dla .NET ignoruje znaczenie val?

1 Zmienna lokalna zadeklarowana jako val nie jest interpretowana jako ostateczna.

class HowAreVarAndValImplementedInScala { 
    var v1 = 123 
    val v2 = 456 

    def method1() = { 
    var v3 = 123 
    val v4 = 456 
    println(v3 + v4) 
    } 
} 

jeśli skompilować powyższy kod scala do kodu bajtowego, a następnie dekompilować, że w Javie, wygląda to tak:

public class HowAreVarAndValImplementedInScala 
{ 
    private int v1 = 123; 
    private final int v2 = 456; 

    public int v1() 
    { 
    return this.v1; 
    } 

    public void v1_$eq(int x$1) { this.v1 = x$1; } 

    public int v2() { return this.v2; } 

    public void method1() { 
    int v3 = 123; 
    int v4 = 456; 
    Predef..MODULE$.println(BoxesRunTime.boxToInteger(v3 + v4)); 
    } 
} 

widzimy v2 jest ostateczna, ale v4 nie jest, to dlaczego?

2 scala kompilator NET dodaje zastąpić słowo kluczowe do wielu (jeśli nie wszystkie) publiczne metody instancji

jeśli skompilować kod scala przedstawioną powyżej w CIL a następnie dekompilacji w C#, to tak:

public class HowAreVarAndValImplementedInScala : ScalaObject 
{ 
    private int v1; 
    private int v2; 

    public override int v1() 
    { 
    return this.v1; 
    } 

    public override void v1_$eq(int x$1) 
    { 
    this.v1 = x$1; 
    } 

    public override int v2() 
    { 
    return this.v2; 
    } 

    public override void method1() 
    { 
    int v3 = 123; 
    int v4 = 456; 
    Predef$.MODULE$.println(v3 + v4); 
    } 

    public HowAreVarAndValImplementedInScala() 
    { 
    this.v1 = 123; 
    this.v2 = 456; 
    } 
} 

wszystkie metody publicznych wystąpień (z wyłączeniem konstruktora) są oznaczone jako zastąpione, dlaczego? czy to konieczne?

3 Scala kompilator NET traci sens val

w powyższym kodzie C#, możemy zauważyć, że v2 jest po prostu normalne pole, podczas gdy w części java Couter, v2 jest oznaczona jako ostateczna powinnam, 't v2 jest oznaczony jako readonly przez kompilator Scala dla .net? (błąd?)

+2

O ile mi wiadomo, 'final' nie ma implikacji runtime w zmiennych lokalnych, ale po prostu podkreślił, że * nie zmienisz wartości *. Pola 'final' w kontraście zakładają na przykład, że zostały zainicjowane po wykonaniu konstruktora. Dlatego ** przypuszczam ** jest pominięty dla 'v4', ponieważ nie ma znaczenia dla maszyny, podczas gdy' v2' musi być 'final' w Javie. Nie jestem jednak wystarczająco pewny, by odpowiedzieć na to pytanie. –

+9

3 pytania powinny być 3 pytania ... –

+0

@MatthiasMeid tak, wydaje się być w porządku – CuiPengFei

Odpowiedz

7

Na poziomie bajtowym, ostateczny nie istnieje dla zmiennych lokalnych. W rzeczywistości sama koncepcja zmiennych lokalnych również nie istnieje. Oznaczenie zmiennej lokalnej jako ostatecznej służy wyłącznie do sprawdzania czasu kompilacji. Ponieważ informacji nie ma w pliku klasy, dekompilator nie ma możliwości odgadnięcia go.

Co do dwóch pierwszych pytań, nie jestem zaznajomiony z kodowaniem CIL, ale gdybym musiał zgadywać, powiedziałbym, że nie ma powodu, aby nie dodawać zastąpienia, a readonly może mieć inną semantykę.

Edycja: Po przejrzeniu specyfikacji CIL, oto co znalazłem.

Ekwiwalent CIL flagi Java final dla pól to initonly, który wydaje się mieć tę samą semantykę. Nie jest jasne, dlaczego kompilator Scala tego nie emituje. Może po prostu się do tego nie zbliżali? A może użyty dekompilator .net nie odzwierciedlał tego. Jeśli chcesz zobaczyć, co faktycznie generuje kompilator, najlepiej jest spojrzeć bezpośrednio na bajtod.

+0

w CIL, to tak: pole prywatne int32 v1 \t.pole prywatne int32 v2 – CuiPengFei

+0

o nadpisaniu: co to jest przesłonięcie? klasa podstawowa nie zawiera żadnego z tych elementów. – CuiPengFei

+0

Pola są bardzo obecne w kodzie bajtowym CIL, jako elementy metadanych '.field'. CIL 'initonly' jest równoważny z' readonly 'w C#. – Virtlink

Powiązane problemy