복붙노트

[SCALA] 어떻게 스칼라 특성은 자바 바이트 코드로 컴파일?

SCALA

어떻게 스칼라 특성은 자바 바이트 코드로 컴파일?

나는 잠시 지금을 위해 스칼라와 함께 주변에 연주 한 나는 특성이 인터페이스와 추상 클래스 모두의 스칼라와 동등한 역할을 할 수 있음을 알고있다. 정확히 어떻게 특성은 자바 바이트 코드로 컴파일?

내가 언급 한 특성을 정확히 그렇지 않으면 추가 클래스 Java 인터페이스 가능한 경우, 인터페이스와 같은 컴파일 몇 가지 짧은 설명을 발견했다. 스칼라 클래스 선형화, 자바에서 사용할 수없는 기능을 달성하는 방법을 나는 아직도, 그러나, 이해가 안 돼요.

특성은 자바 바이트 코드로 컴파일하는 방법을 설명하는 좋은 소스가 있습니까?

해결법

  1. ==============================

    1.나는 전문가가 아니지만, 여기 나의 이해는 다음과 같습니다

    나는 전문가가 아니지만, 여기 나의 이해는 다음과 같습니다

    형질 인터페이스 및 대응하는 클래스로 컴파일된다.

    trait Foo {
      def bar = { println("bar!") }
    }
    

    동등하게 ...

    public interface Foo {
      public void bar();
    }
    
    public class Foo$class {
      public static void bar(Foo self) { println("bar!"); }
    }
    

    푸 $ 클래스의 정적 줄 방법이 어떻게 호출되는 않는 : 어떤 질문을 남긴다? 이 마법은 푸 특성이 혼합되어있는 클래스의 컴파일러에 의해 수행된다.

    class Baz extends Foo
    

    같은됩니다 ...

    public class Baz implements Foo {
      public void bar() { Foo$class.bar(this); }
    }
    

    클래스 선형화 단지 언어 사양에 정의 된 선형 규칙에 따른 방법의 적절한 버전합니다 (XXXX $ 클래스 클래스의 정적 메소드를 호출)를 구현합니다.

  2. ==============================

    2.이를 살펴보기 위해, 모두 추상적이고 구체적인 방법과 여러 특성을 사용하여 다음 스칼라의 예를 살펴 보자 :

    이를 살펴보기 위해, 모두 추상적이고 구체적인 방법과 여러 특성을 사용하여 다음 스칼라의 예를 살펴 보자 :

    trait A {
      def foo(i: Int) = ???
      def abstractBar(i: Int): Int
    }
    
    trait B {
      def baz(i: Int) = ???
    }
    
    class C extends A with B {
      override def abstractBar(i: Int) = ???
    }
    

    순간 (스칼라 2.11로서, 즉) 한 특성은 다음과 같이 인코딩된다 :

    이 부호화의 주요 장점은 콘크리트 부재가없는 특성이 (인터페이스 동형이다) 실제로 인터페이스로 컴파일된다는 것이다.

    interface A {
        int foo(int i);
        int abstractBar(int i);
    }
    
    abstract class A$class {
        static void $init$(A $this) {}
        static int foo(A $this, int i) { return ???; }
    }
    
    interface B {
        int baz(int i);
    }
    
    abstract class B$class {
        static void $init$(B $this) {}
        static int baz(B $this, int i) { return ???; }
    }
    
    class C implements A, B {
        public C() {
            A$class.$init$(this);
            B$class.$init$(this);
        }
    
        @Override public int baz(int i) { return B$class.baz(this, i); }
        @Override public int foo(int i) { return A$class.foo(this, i); }
        @Override public int abstractBar(int i) { return ???; }
    }
    

    그러나, 스칼라 2.12 자바 (8)이 필요하며, 따라서 사용하는 기본 방법 및 인터페이스에 정적 메서드 등이 같은 결과 외모에 할 수있다 :

    interface A {
        static void $init$(A $this) {}
        static int foo$(A $this, int i) { return ???; }
        default int foo(int i) { return A.foo$(this, i); };
        int abstractBar(int i);
    }
    
    interface B {
        static void $init$(B $this) {}
        static int baz$(B $this, int i) { return ???; }
        default int baz(int i) { return B.baz$(this, i); }
    }
    
    class C implements A, B {
        public C() {
            A.$init$(this);
            B.$init$(this);
        }
    
        @Override public int abstractBar(int i) { return ???; }
    }
    

    당신이 볼 수 있듯이, 정적 방법과 전달자와 기존의 디자인을 유지하고있다, 그들은 단지 인터페이스에 접혀. 형질의 구체적인 방법은 이제 정적 방법으로 인터페이스 자체로 이동 한 전달자 방법은 모든 클래스에서 합성되지만 기본 방법으로 한 번 정의하고 (형질의 본문에 코드를 나타냅니다) $ 방법 초기화 정적의 $되지 않습니다 동반자 정적 클래스가 필요하고,뿐만 아니라 인터페이스로 이동되었습니다.

    그것은 아마도 다음과 같이 단순화 할 수 있습니다 :

    interface A {
        static void $init$(A $this) {}
        default int foo(int i) { return ???; };
        int abstractBar(int i);
    }
    
    interface B {
        static void $init$(B $this) {}
        default int baz(int i) { return ???; }
    }
    
    class C implements A, B {
        public C() {
            A.$init$(this);
            B.$init$(this);
        }
    
        @Override public int abstractBar(int i) { return ???; }
    }
    

    나는이 작업이 완료되지 않은 이유를 모르겠어요. 언뜻 보면, 현재의 인코딩이 우리에게 전달 호환성의 비트를 줄 수 있습니다 당신이 이전 컴파일러로 컴파일 된 클래스와 새로운 컴파일러로 컴파일 특성을 사용할 수 있습니다, 그 오래된 클래스는 단순히 그들과의 인터페이스에서 상속 방법 전달자 기본을 무시합니다 동일한 사람. 전달자 방법 달러 (A $) 클래스와 B의 $ 클래스 더 이상 존재는, hypothetic 전달 호환성이하는 그래서 실제로 작업에 정적 메소드를 호출하려고합니다 제외.

  3. ==============================

    3.이것의 아주 좋은 설명입니다 :

    이것의 아주 좋은 설명입니다 :

    바쁜 자바 프로그래머를위한 스칼라 입문 : 특성과 행동의 - JVM의 특색

    인용문:

  4. ==============================

    4.스칼라 (12)와 자바 (8)의 맥락에서, 당신은 8020cd6 커밋 다른 설명을 볼 수 있습니다 :

    스칼라 (12)와 자바 (8)의 맥락에서, 당신은 8020cd6 커밋 다른 설명을 볼 수 있습니다 :

    interface T {
      default int m() { return 1 }
      static int m$(T $this) { <invokespecial $this.m()> }
    }
    class C implements T {
      public int m() { return T.m$(this) }
    }
    
  5. from https://stackoverflow.com/questions/2557303/how-are-scala-traits-compiled-into-java-bytecode by cc-by-sa and MIT license