2013-05-08 2 views
7

나는 스칼라를 가지고 놀고있다. 3 개의 재미있는 것을 발견했습니다 (제목은 세 번째 것입니다)..NET 용 스칼라 컴파일러가 val의 의미를 무시하는 이유는 무엇입니까?

1 val로 선언 된 지역 변수는 final로 해석되지 않습니다.

class HowAreVarAndValImplementedInScala { 
    var v1 = 123 
    val v2 = 456 

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

내가 바이트 코드로 위의 스칼라 코드를 컴파일하고 자바로 그 디 컴파일, 그것은 다음과 같습니다 경우 :

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)); 
    } 
} 

우리가 v2에서 최종 볼 수 있지만 V4가 아닌, 그 이유는 무엇입니까?

는 .NET 용

2 스칼라 컴파일러는이처럼, 우리는 위의 CIL에 후 디 컴파일 C 번호로 표시된 스칼라 코드를 컴파일 할 경우 (전부는 아니지만) 많은 공공 인스턴스 메소드

을 키워드를 오버라이드 (override) 추가 :

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; 
    } 
} 

모든 공용 인스턴스 메소드 (생성자를 제외) 오버라이드로 표시되는 이유는 무엇입니까? 그게 필요한가요?

자바 couter 부분에서, V2는 최종으로 표시되는 동안 .NET 3 스칼라 컴파일러 브로

의미 상기 C# 코드에

, 우리는 그 V2 단지 일반 필드 볼 수 느슨해

, shouldn 't v2는 .net 용 스칼라 컴파일러에서 읽기 전용으로 표시됩니다. (버그?)

+2

필자가 아는 한 'final'은 지역 변수에 런타임 의미가 없지만 * 값을 변경하지 않을 것이라고 강조했습니다. 대조적으로 '최종'필드는 생성자가 실행 된 후에 초기화된다는 것을 의미합니다. 따라서 ** v4는 컴퓨터와 관련이 없으므로 생략됩니다. 반면에 v2는 Java에서 final이어야합니다. 그러나 나는이 대답을하기에 충분하지 않다. –

+9

3 개의 질문은 3 가지 질문이어야합니다 ... –

+0

@MatthiasMeid 예, 올바르게 보입니다 – CuiPengFei

답변

7

바이트 코드 레벨에서 final은 로컬 변수에 존재하지 않습니다. 실제로 로컬 변수 자체의 개념 자체도 실제로 존재하지 않습니다. 지역 변수를 final로 표시하는 것은 순전히 컴파일 시간을 검사하는 것입니다. 정보가 클래스 파일에 없기 때문에 디 컴파일러는 추측 할 방법이 없습니다.

두 번째 두 가지 질문에 대해서는 CIL 바이트 코드에 익숙하지 않지만 무시할 이유가 없다고 생각하면 readonly에 다른 의미가있을 수 있습니다.

편집 : CIL 사양을 살펴본 결과 다음은 내가 찾은 것입니다.

필드에 대한 Java의 final 플래그와 동일한 CIL은 initonly이며 동일한 의미를 갖는 것으로 보입니다. 스칼라 컴파일러가 왜 이것을 내 보내지 않는지는 명확하지 않습니다. 아마 그들은 단지 주변에 가지 않았을 것입니까? 또는 아마도 당신이 사용했던 .net 디 컴파일러가 이것을 반영하지 않았을 것입니다. 컴파일러가 실제로 생성하는 것을보고 싶다면 직접 바이트 코드를 살펴 보는 것이 가장 좋습니다.

+0

은 다음과 같습니다. .field private int32 v1 \t.필드 개인 비공개 int32 v2 – CuiPengFei

+0

오버라이드 : 무엇이 오버라이드합니까? 기본 클래스는 이들 멤버를 포함하지 않는다. – CuiPengFei

+0

필드는 CIL 바이트 코드에 '.field'메타 데이터 요소로 매우 많이 존재한다. 그리고 CIL'initonly'는 C#의'readonly'와 동일합니다. – Virtlink

관련 문제