스칼라에서 자기 유형과 형질 상속의 차이점은 무엇입니까?


9

Google 검색시이 주제에 대한 많은 답변이 나타납니다. 그러나 나는이 두 기능의 차이점을 잘 설명하는 사람이 있다고 생각하지 않습니다. 한 번 더 시도하고 싶습니다. 구체적으로 ...

자기 유형으로 할 수 있고 상속하지 않고 할 수있는 것은 무엇입니까?

나에게, 둘 사이에 정량화 할 수있는 물리적 차이가 있어야한다. 그렇지 않으면 명목상 다르다.

특성 A가 B 또는 자체 유형 B를 확장하는 경우 B의 존재가 요구 사항이라는 것을 모두 설명하지 않습니까? 차이점은 어디에 있습니까?


현상금에 설정 한 조건에주의합니다. 우선, 이것이 모든 소프트웨어라는 점에서 "물리적"차이를 정의하십시오. 그 외에도 믹스 인을 사용하여 생성하는 모든 복합 객체 의 경우 가시적 인 방법으로 순수하게 함수를 정의하면 상속 기능으로 대략적인 것을 만들 수 있습니다. 그것들이 다른 곳은 확장 성, 유연성 및 구성 성입니다.
itsbruce

다양한 크기의 강판이 있으면 함께 볼트로 묶어 상자를 만들거나 용접 할 수 있습니다. 하나의 좁은 관점에서는 기능면에서 동등합니다. 하나를 쉽게 재구성하거나 확장 할 수 있고 다른 하나는 할 수 없다는 사실을 무시하면 말입니다. 나는 당신이 당신의 기준에 대해 더 많이 말하면 잘못되었다는 것이 기쁘지 만, 당신은 그것들이 동등한 것이라고 주장 할 것이라고 생각합니다.
itsbruce

나는 당신이 일반적으로 말하는 것에 익숙하지만,이 특별한 경우의 차이점이 무엇인지 여전히 이해하고 있지 않습니다. 한 방법이 다른 방법보다 확장 가능하고 유연하다는 것을 보여주는 코드 예제를 제공 할 수 있습니까? * 확장 기능이있는 기본 코드 * 자체 유형이있는 기본 코드 * 확장 스타일에 추가 된 기능 * 자체 유형 스타일에 추가 된 기능
Mark Canlas

좋아, 현상금이 다 떨어지기 전에 그것을 시도 할 수 있다고 생각합니다;)
itsbruce

답변:


11

특성 A가 B를 확장하면 A를 혼합하면 A에 추가하거나 확장하는 모든 것을 정확하게 B에 더 해줍니다. 반대로, 특성 A에 명시 적으로 B로 유형이 지정된 자체 참조가있는 경우 최종 상위 클래스는 B 또는 하위 유형의 B 도 혼합해야합니다 ( 먼저 이를 혼합해야 합니다).

그것이 가장 중요한 차이점입니다. 첫 번째 경우, 정확한 유형의 B는 A 지점이 연장되는 지점에서 결정화됩니다. 두 번째로, 부모 클래스의 디자이너는 부모 클래스가 구성되는 시점에서 어떤 버전의 B가 사용되는지 결정합니다.

또 다른 차이점은 A와 B가 같은 이름의 메소드를 제공하는 것입니다. A가 B를 확장하는 경우 A의 방법은 B보다 우선합니다. A가 B 다음에 섞인 경우 A의 방법이 단순히 이깁니다.

입력 된 자체 참조는 훨씬 더 많은 자유를줍니다. A와 B의 커플 링이 느슨합니다.

최신 정보:

이러한 차이점의 이점에 대해 명확하지 않기 때문에 ...

직접 상속을 사용하는 경우 B + A 인 특성 A를 만듭니다. 당신은 돌로 관계를 설정했습니다.

유형이 지정된 자체 참조를 사용하는 경우 클래스 C에서 특성 A를 사용하려는 사람은 누구나

  • B와 A를 C에 섞는다.
  • B의 하위 유형을 혼합 한 다음 A를 C에 혼합하십시오.
  • A를 C에 혼합하십시오. 여기서 C는 B의 서브 클래스입니다.

스칼라가 코드 블록을 생성자로 사용하여 특성을 직접 인스턴스화 할 수있는 방법을 고려할 때 이는 옵션의 한계가 아닙니다.

A의 방법 우승 의 차이점은 A가 B를 확장하는 A와 비교하여 마지막에 혼합되기 때문에 이것을 고려하십시오 ...

일련의 특성을 혼합하는 foo()경우, 메소드 가 호출 될 때마다 컴파일러는 혼합 된 마지막 특성으로 이동 foo()한 다음 (찾을 수없는 경우) 구현 foo()하고 사용 하는 특성을 찾을 때까지 순서를 왼쪽으로 탐색 합니다. 그. A에는 호출 옵션 super.foo()이 있으며 구현을 찾을 때까지 시퀀스를 왼쪽으로 이동합니다.

따라서 A가 B에 대한 자체 참조 유형을 가지고 있고 A의 작성자가 B가 구현 한다는 것을 알고 있다면 foo()A는 super.foo()아무것도 제공하지 않으면 foo()B가 할 것이라는 것을 알 수 있습니다 . 그러나 클래스 C의 작성자는를 구현하는 다른 특성을 제거하는 옵션이 있으며 foo()대신 A 가이를 얻습니다.

다시 말하지만 이것은 A 확장 B보다 훨씬 강력하고 제한이 적으며 B의 버전을 직접 호출 foo()합니다.


승리와 재정의의 차이점은 무엇입니까? 다른 메커니즘을 통해 두 경우 모두 A를 받고 있습니까? 그리고 첫 번째 예에서 ... 첫 번째 단락에서 특성 A가 SuperOfB를 확장하지 않는 이유는 무엇입니까? 우리는 항상 두 가지 메커니즘을 사용하여 문제를 리모델링 할 수 있다고 생각합니다. 이것이 불가능한 유스 케이스가 보이지 않는 것 같습니다. 아니면 너무 많은 것을 가정하고 있습니다.
마크 Canlas

음, B가 필요한 것을 정의한다면 왜 A가 B의 서브 클래스를 확장하도록 하고 싶 습니까? 자체 참조는 B (또는 서브 클래스)가 존재하도록 강제하지만 개발자가 선택할 수 있는가? B를 확장하는 한, 특성 A를 쓴 후에 그들이 쓴 내용을 혼합 할 수 있습니다. 특성 A를 쓸 때 이용 가능한 것만으로 제한하는 이유는 무엇입니까?
itsbruce

차이를 명확하게하기 위해 업데이트되었습니다.
itsbruce

@itsbruce 개념적 차이가 있습니까? IS-A 대 HAS-A?
Jas

@Jas 특성 AB 의 관계 와 관련하여 상속은 IS-A 이고 입력 된 자체 참조는 HAS-A (구성 적 관계)를 제공합니다. 특성이 혼합 된 클래스의 경우 결과는 IS-A 입니다.
itsbruce

0

자체 유형을 설정하거나 설정할 때의 wrt 가시성 및 "기본"구현의 차이점을 보여주는 코드가 있습니다. 실제 이름 충돌이 해결되는 방법에 대해 이미 논의한 부분은 설명하지 않고 가능한 것과 불가능한 것에 중점을 둡니다.

trait A1 {
  self: B =>

  def doit {
    println(bar)
  }
}

trait A2 extends B {
  def doit {
    println(bar)
  }
}

trait B {
  def bar = "default bar"
}

trait BX extends B {
  override def bar = "bar bx"
}

trait BY extends B {
  override def bar = "bar by"
}

object Test extends App {
  // object Thing1 extends A1  // FAIL: does not conform to A1 self-type
  object Thing1 extends A1 with B
  object Thing2 extends A2

  object Thing1X extends A1 with BX
  object Thing1Y extends A1 with BY
  object Thing2X extends A2 with BX
  object Thing2Y extends A2 with BY

  Thing1.doit  // default bar
  Thing2.doit  // default bar
  Thing1X.doit // bar bx
  Thing1Y.doit // bar by
  Thing2X.doit // bar bx
  Thing2Y.doit // bar by

  // up-cast
  val a1: A1 = Thing1Y
  val a2: A2 = Thing2Y

  // println(a1.bar)    // FAIL: not visible
  println(a2.bar)       // bar bx
  // println(a2.bary)   // FAIL: not visible
  println(Thing2Y.bary) // 42
}

IMO의 중요한 차이점 중 하나는 (업 캐스트 된 부분에서 설명 된 것처럼) 단순히 보는 것에 만 A1필요하다는 것을 드러내지 않는다는 것입니다 . 실제로 특정 전문화 가 사용되는 것을 볼 수있는 유일한 코드 는 구성된 유형 (와 같은 ) 을 명시 적으로 알고있는 코드입니다 .BA1BThink*{X,Y}

또 다른 요점은 A2(확장자와 함께) 실제로 B다른 것을 지정하지 않으면 실제로 사용 A1한다는 것입니다 (자체 유형)은 B재정의하지 않는 한 사용할 것이라고 말하지 않으며 객체가 인스턴스화 될 때 콘크리트 B가 명시 적으로 주어져야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.