복붙노트

[SCALA] 스칼라에서 선형화 순서

SCALA

스칼라에서 선형화 순서

나는 특성 작업을 할 때 스칼라의 선형화 순서를 이해하는데 어려움이 :

class A {
  def foo() = "A"
}

trait B extends A {
  override def foo() = "B" + super.foo()
}

trait C extends B {
  override def foo() = "C" + super.foo()
}

trait D extends A {
  override def foo() = "D" + super.foo()
}

object LinearizationPlayground {
    def main(args: Array[String]) {

      var d = new A with D with C with B;
      println(d.foo) // CBDA????
  }    
}

그것은 CBDA를 인쇄하지만 난 그 이유를 알아낼 수 없습니다. 형질의 순서는 어떻게 결정됩니까?

고마워

해결법

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

    1.선형화에 대한 이유에 대한 직관적 인 방법은 시공 순서를 참조하고 선형 계층 구조를 시각화하는 것입니다.

    선형화에 대한 이유에 대한 직관적 인 방법은 시공 순서를 참조하고 선형 계층 구조를 시각화하는 것입니다.

    이 방법을 생각할 수있다. 베이스 클래스가 먼저 생성되고; 하지만 기본 클래스를 구성 할 수되기 전에, 그 슈퍼 클래스는 / 특성 (이 수단 건설이 계층 구조의 상위부터) 먼저 구성해야합니다. 계층 구조의 각 클래스의 경우, 혼합 - 인 특성 왼쪽에서 오른쪽 오른쪽의 특성은 "나중에"따라서 추가 "재정의"이전 특성에 기회가되어 구성되어 있기 때문이다. 그러나 유사하게 클래스, 형질을 구성하기 위해, 자사의 기본 특성은 첫 번째 (명백한)로 구성되어야한다 형질 이미 (계층 구조의 어느 곳)로 구성되어있는 경우와 매우 합리적으로,이를 다시 복원되지 않습니다. 이제, 건축 순서는 선형화의 반대입니다. 선형 계층 구조에서 상위로 "기본"특성 / 클래스의 생각과 특성은 선형화의 대상이되는 클래스 / 객체 가까이로 계층 구조에서 내립니다. 선형화는 super'이 특성에 해결하는 방법`에 영향이 가장 가까운 기본 특성 (계층 구조에서 이상)으로 해결됩니다.

    그러므로:

    var d = new A with D with C with B;
    

    B와 C와 D와의 선형화는

    선형화 그래서입니다 : A-D-B-C. 당신은 루트 (최고)이며, 처음으로 구성되어 선형 계층 구조로 생각할 수 있고, C는 잎 (최저)와 마지막 구성입니다. C는 마지막으로 구성되어, 그것은 그 "이전"멤버를 오버라이드 (override) 할 수 있습니다 의미합니다.

    이러한 직관적 인 규칙을 감안할 때, d.foo는 B에합니다 (즉, 높은 / 이전, 선형화에, B의 왼쪽에있는 특성을) 해결 super.foo 다음에 "C"를 반환 C.foo을, ()를 호출 이는 super.foo 다음에 "B"를 반환 () 마지막으로 "A"를 반환 A,에 해결 super.foo 다음에 "D"를 () 반환 D에 해결된다. 당신이 "CBDA"가 그래서.

    또 다른 예를 들어, 나는 다음과 같은 일을 준비 :

    class X { print("X") }
    class A extends X { print("A") }
    trait H { print("H") }
    trait S extends H { print("S") }
    trait R { print("R") }
    trait T extends R with H { print("T") }
    class B extends A with T with S { print("B") }
    
    new B  // X A R H T S B     (the prints follow the construction order)
    
    // Linearization is the reverse of the construction order.
    // Note: the rightmost "H" wins (traits are not re-constructed)
    // lin(B) = B >> lin(S) >> lin(T) >> lin(A)
    //        = B >> (S >> H) >> (T >> H >> R) >> (A >> X)
    //        = B >> S >> T >> H >> R >> A >> X
    
  2. ==============================

    2.허용 대답은 단순화를 위해, 나는 다른 방식으로 그것을 설명하기 위해 최선을 다하고자하지만, 훌륭합니다. 희망은 어떤 사람들을 도울 수 있습니다.

    허용 대답은 단순화를 위해, 나는 다른 방식으로 그것을 설명하기 위해 최선을 다하고자하지만, 훌륭합니다. 희망은 어떤 사람들을 도울 수 있습니다.

    당신은 선형화 문제가 발생하는 경우, 첫 번째 단계는 클래스와 특성의 계층 구조 트리를 그릴 것입니다. 이 특정 예를 들어, 계층 구조 트리는 다음과 같이 될 것이다 :

    두 번째 단계는 대상 문제를 방해 특색 및 클래스의 모든 선형을 작성하는 것입니다. 당신은 모든 마지막 단계 전에 하나를해야합니다. 이를 위해, 당신은 루트에 도달하기 위해 단지 경로를 작성해야합니다. 특성의 선형화는 다음과 같다 :

    L(A) = A
    L(C) = C -> B -> A
    L(B) = B -> A
    L(D) = D -> A
    

    세 번째 단계는 문제의 선형화를 작성하는 것입니다. 이러한 특정 문제에서 우리의 선형화를 해결하기 위해 계획

    중요 사항은 먼저 마우스 오른쪽 첫째, 깊이 우선 검색을 사용하여 메소드 호출을 해결하는 규칙이 있다는 것입니다. 다른 단어, 당신은 가장 오른쪽에서 선형화를 쓰기 시작한다. 그것은 다음과 같다 : L (B) >> L (C) >> L (D) >> L (A)

    네 번째 단계는 가장 간단한 단계입니다. 단지 세 번째 단계에 두 번째 단계에서 각 선형 대체. 대체 후에는 다음과 같이해야합니다 :

    B -> A -> C -> B -> A -> D -> A -> A
    

    마지막으로, 당신은 지금 왼쪽에서 오른쪽으로 모든 중복 클래스를 제거해야합니다. 굵은 문자를 제거해야합니다 :     B -> A -> C -> B -> A -> D -> A ->을

    > B - -> D ->은 C : 당신은 당신이 결과를 참조 따라서 답은 CBDA이다.

    나는 개별적으로 깊은 개념 설명 아니라는 것을 알고,하지만 난 생각 개념 설명을위한 보완 적으로 도움이 될 수 있습니다.

    그리고이 부분은 공식에 의존하여 설명합니다 :

     Lin(new A with D with C with B) = {A, Lin(B), Lin(C), Lin(D)}
     Lin(new A with D with C with B) = {A, Lin(B), Lin(C), {D, Lin(A)}}
     Lin(new A with D with C with B) = {A, Lin(B), Lin(C), {D, A}}
     Lin(new A with D with C with B) = {A, Lin(B), {C, Lin(B)}, {D, A}}
     Lin(new A with D with C with B) = {A, Lin(B), {C, {B, Lin(A)}}, {D, A}}
     Lin(new A with D with C with B) = {A, Lin(B), {C, {B, A}}, {D, A}}
     Lin(new A with D with C with B) = {A, {B, A}, {C, {B, A}}, {D, A}}
     Lin(new A with D with C with B) = {C,B,D,A}
    
  3. ==============================

    3.당신은 한 번에 하나를 추가하여 볼 수 있도록 스칼라의 특성은, 스택 :

    당신은 한 번에 하나를 추가하여 볼 수 있도록 스칼라의 특성은, 스택 :

    다음은 스칼라는 다이아몬드 상속 문제를 해결하는 방법에 대한 블로그 게시물입니다.

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

    4.슈퍼 통화가 선형화 호출되는 스칼라 해결하는 프로세스 귀하의 예제에서는 같은 객체를 생성

    슈퍼 통화가 선형화 호출되는 스칼라 해결하는 프로세스 귀하의 예제에서는 같은 객체를 생성

    var d = new A with D with C with B;
    

    지정된 스칼라 참조 문서는 여기에 슈퍼에 전화 그래서뿐만 해결 될 것

    l(A) = A >> l(B) >> l(c) >> l(D)
    
    l(A) = A >> B >> l(A) >> l(C) >> l(D)
    
    l(A) = A >> B >> A >> C >> l(B) >> l(D)
    
    l(A) = A >> B >> A >> C >> B >> l(A) >> l(D)
    
    l(A) = A >> B >> A >> C >> B >> A >> l(D)
    
    l(A) = A >> B >> A >> C >> B >> A >> D >> l(A)
    
    l(A) = A >> B >> A >> C >> B >> A >> D >> A
    

    권리를이기는 될에 남아 제거 중복 구조에서 이제 시작

    예를 들면 을 제거하고 우리가 얻을

    l(A) = B >> C >> B >> D >> A
    

    B를 제거하고 우리가 얻을

    l(A) = C >> B >> D >> A
    

    여기에서 우리는 중복 항목이 없습니다 이제 C에서 호출을 시작

    B C D

    클래스 C의 super.foo는 D에 등 B 호에 foo B에서 foo는 foo 함수를 호출합니다.

    추신 여기서 L (A)는 (A)의 선형 인

  5. ==============================

    5.다른 anwsers뿐만 아니라 당신은 조각 결과 아래의 단계별 설명을 찾을 수 있습니다

    다른 anwsers뿐만 아니라 당신은 조각 결과 아래의 단계별 설명을 찾을 수 있습니다

    hljs.initHighlightingOnLoad (); <스크립트 SRC = "// cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"> <링크 HREF = "// cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/styles/zenburn.min.css"확인해 = "스타일 시트"/> <링크 HREF = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"REL = "스타일"/> <표 클래스 = "테이블">        <제> 식     <제>에서     <제> <부호> foo는 () 결과            <클래스 코드 = "스칼라"> 새로 만들기 <사전>을           <사전> <클래스 코드 = "스칼라">은           <클래스 코드 = "스칼라"> <사전>을 "A"                 D로 <클래스 코드 = "스칼라"> 새로 만들기 <사전>을           <사전> <클래스 코드 = "스칼라"> D           <클래스 코드 = "스칼라"> <사전>을 "DA"                      C와 D와 <클래스 코드 = "스칼라"> 새로 만들기 <사전>을           C와 <클래스 코드 = "스칼라"> D <사전>을           <클래스 코드 = "스칼라"> <사전> "를 CBDA"                     B와 C와 D와 <클래스 코드 = "스칼라"> 새로 만들기 <사전>을           C와 <클래스 코드 = "스칼라"> D <사전>을           <클래스 코드 = "스칼라"> <사전> "를 CBDA"        

  6. ==============================

    6.

    class Combined extends A with D with C with B {
      final <superaccessor> <artifact> def super$foo(): String = B$class.foo(Combined.this);
      override def foo(): String = C$class.foo(Combined.this);
      final <superaccessor> <artifact> def super$foo(): String = D$class.foo(Combined.this);
      final <superaccessor> <artifact> def super$foo(): String =  Combined.super.foo();
      def <init>(): Combined = {
        Combined.super.<init>();
        D$class./*D$class*/$init$(Combined.this);
        B$class./*B$class*/$init$(Combined.this);
        C$class./*C$class*/$init$(Combined.this);
        ()
      }
    };
    

    왼쪽에서 오른쪽으로 당신은 읽을 수 있습니다. 여기서 작은 예이다. 즉 초기화 확장 할 때 세 가지 특성은 그들의 이름을 인쇄합니다 :

    scala> trait A {println("A")}
    scala> trait B {println("B")}
    scala> trait C {println("C")}
    
    scala> new A with B with C
      A
      B
      C
    res0: A with B with C = $anon$1@5e025e70
    
    scala> new A with C with B
     A
     C
     B
    res1: A with C with B = $anon$1@2ed94a8b
    

    그래서이 기본 선형화 순서입니다. 그래서 마지막은 이전을 덮어 쓰게됩니다.

    귀하의 문제는 좀 더 복잡하다. 이미 다른 특성을 확장 특성으로 자체는 이전 특성의 일부 값을 오버라이드 (override)하는 것을. 그러나 초기화 순서는 왼쪽에서 오른쪽으로 또는 오른쪽에서 왼쪽 우선합니다.

    당신은 특성 자체가 처음으로 초기화된다는 것을 명심해야한다.

  7. ==============================

    7.그런데 사실은 내가 그냥 먼저의 생성자 선형화를 이해 할 수 있도록, 내가 아주 간단이 생각하는 생성자 선형화를 역전 참조

    그런데 사실은 내가 그냥 먼저의 생성자 선형화를 이해 할 수 있도록, 내가 아주 간단이 생각하는 생성자 선형화를 역전 참조

    object Linearization3 {
      def main(args: Array[String]) {
        var x = new X
        println()
        println(x.foo)
      }
    }
    
    class A {
      print("A")
    
      def foo() = "A"
    }
    
    trait B extends A {
      print("B")
    
      override def foo() =   super.foo() + "B" // Hence I flipped yours to give exact output as constructor
    }
    
    trait C extends B {
      print("C")
    
      override def foo() =  super.foo() + "C"
    }
    
    trait D extends A {
      print("D")
    
      override def foo() =  super.foo() + "D"
    }
    
    class X extends A with D with C with B
    

    어떤 출력 :

    ADBC
    ADBC
    

    그래서 여기에 방법입니다 (중복없이) 바로 그때 반복적으로 쓰기 출력 왼쪽에서 난 그냥 하나에 의해 클래스 / 특성 하나를 가지고 출력을 계산합니다 :

    object Linearization3 {
      def main(args: Array[String]) {
        var x = new X
        println()
        println(x.foo)
      }
    }
    
    class A {
      print("A")
    
      def foo() = "A"
    }
    
    trait B extends A {
      print("B")
    
      override def foo() = "B" + super.foo()
    }
    
    trait C extends B {
      print("C")
    
      override def foo() = "C" + super.foo()
    }
    
    trait D extends A {
      print("D")
    
      override def foo() = "D" + super.foo()
    }
    
    class X extends A with D with C with B
    

    출력은 다음과 같습니다

    ADBC
    CBDA
    

    나는 나 같은 초보자를위한 간단한 충분했다 희망

  8. from https://stackoverflow.com/questions/34242536/linearization-order-in-scala by cc-by-sa and MIT license