스칼라의 특성은 어떻게“다이아몬드 오류”를 피합니까?


16

(참고 : 명백한 이유로 제목에서 '문제'대신 '오류'를 사용했습니다 ..;)).

Scala의 Traits에 대한 기본적인 내용을 읽었습니다. Java 또는 C #의 인터페이스와 유사하지만 메소드의 기본 구현을 허용합니다.

궁금한 점이 있는데, 이것이 "다이아몬드 문제"의 원인이 될 수없는 이유입니다. 이것이 많은 언어가 다중 상속을 먼저 ​​피하는 이유입니다.

그렇다면 스칼라는 이것을 어떻게 처리합니까?


당신의 연구를 공유하면 모든 사람을 도울 수 있습니다. 당신이 무엇을 시도했고 왜 그것이 당신의 요구를 충족시키지 못했는지 알려주십시오. 이것은 당신이 시간을내어 자신을 돕기 위해 노력했고, 명백한 답변을 되풀이하는 것을 막아 주며, 무엇보다도 더 구체적이고 관련있는 답변을 얻는 데 도움이됩니다. 또한 물어
gnat

2
@ gnat : 이것은 구체적인 문제가 아니라 개념적 질문입니다. "스칼라에이 수업이 있는데 다이아몬드 문제와 관련이 있다고 생각되는 문제가 생기면 어떻게 해결해야합니까?" 귀하의 의견은 적절하지만 질문은 SO에 속합니다. : P
Mason Wheeler

@ MasonWheeler 나는 스칼라에 대한 기본적인 독서를했습니다. 필자가 읽은 내용에서 "diamond"를 처음 검색하면 "특성은 Java 인터페이스 구문의 모든 기능을 갖지만, 특성은 메소드를 구현할 수 있습니다. Ruby에 익숙한 경우 특성은 비슷합니다. 많은 특성을 단일 클래스로 혼합 할 수 있습니다. 특성은 생성자 매개 변수를 사용할 수 없지만 클래스처럼 작동하지 않습니다. 이는 다이아몬드 문제없이 다중 상속에 접근 할 수있는 기능을 제공합니다. " 이 질문에 대한 노력의 부족은 다소 뻔뻔한 느낌
gnat

7
그 진술을 읽는 것이 단지 그렇게하는 방법을 알려주지는 않습니다.
Michael Brown

답변:


22

다이아몬드 문제는 선택할 방법의 구현을 결정할 수 없다는 것입니다. Scala는 언어 사양의 일부로 선택할 구현을 정의하여이 문제를 해결합니다 ( 이 Wikipedia 기사에서 Scala에 대한 부분 읽기 ).

물론, 동일한 순서 정의가 클래스 다중 상속에서도 사용될 수 있습니다. 왜 특성에 귀찮습니까?

IMO가 생성자 인 이유. 생성자는 일반 메소드가 가지고 있지 않은 몇 가지 제한 사항이 있습니다-객체마다 한 번만 호출 할 수 있으며 각 새 객체에 대해 호출해야하며 하위 클래스 생성자는 첫 번째 명령이므로 부모의 생성자를 호출해야합니다 (대부분의 언어는 매개 변수를 전달할 필요가 없으면 암시 적으로 수행하십시오).

B와 C가 A와 D를 상속하고 B와 C의 생성자가 모두 A의 생성자를 호출하면 D의 생성자는 A의 생성자를 두 번 호출합니다. 스칼라처럼 때문에 방법이 여기에 작동하지 않습니다를 선택할 수있는 구현 정의 모두 B의와 C의 생성자를 호출해야합니다.

특성은 생성자가 없기 때문에이 문제를 피합니다.


1
C3 선형화 를 사용 하여 생성자를 한 번만 호출 할 수 있습니다 . 이것이 파이썬이 다중 상속을 수행하는 방식입니다. 내 머리 꼭대기에서 D <B | C <A 다이아몬드는 D-> B-> C-> A에 대한 선형화입니다. 또한 Google 검색에 따르면 스칼라 특성에 가변 변수가있을 수 있으므로 분명히 거기 어딘가에 생성자? 그러나 그것이 후드 아래에서 컴포지션을 사용하고 있다면 (나는 모른다, 스칼라를 사용한 적이 없다) B와 C가 A의 인스턴스를 공유 할 수 있다는 것을보기 힘들지 않다.
Doval

... 트레이 트는 인터페이스 상속과 구성 + 위임을 결합하는 모든 상용구를 표현하는 매우 간결한 방법처럼 보입니다. 이는 행동을 재사용하는 올바른 방법입니다.
Doval

@Doval 상속 된 파이썬에서 생성자에 대한 나의 경험은 그들이 왕의 고통이라는 것입니다. 각 생성자는 호출 순서를 알 수 없으므로 부모 생성자의 서명이 무엇인지 모릅니다. 일반적인 해결책은 모든 생성자가 많은 키워드 인수를 가져 와서 사용하지 않는 것을 슈퍼 생성자로 전달하는 것이지만 해당 규칙을 따르지 않는 기존 클래스로 작업 해야하는 경우 안전하게 상속 할 수 없습니다 그것.
James_pic

또 다른 질문은 C ++이 다이아몬드 문제에 대해 제정신 정책을 선택하지 않은 이유입니다.
사용자

20

스칼라는 "특성 선형화 (trait linearization)"로 다이아몬드 문제를 피합니다. 기본적으로 오른쪽에서 왼쪽으로 확장하는 특성에서 메소드 구현을 찾습니다. 간단한 예 :

trait Base {
   def op: String
}

trait Foo extends Base {
   override def op = "foo"
}

trait Bar extends Base {
   override def op = "bar"
}

class A extends Foo with Bar
class B extends Bar with Foo

(new A).op
// res0: String = bar

(new B).op
// res1: String = foo

그러나, 특성 목록에는 다른 특성을 확장 할 수 있으므로 명시 적으로 제공 한 특성 목록이 포함되어있을 수 있습니다. 자세한 설명은 다음과 같습니다. 스택 가능한 수정으로서의 특성과 여기에 선형화의보다 완전한 예 : 다중 상속이 아닌 이유는 무엇입니까?

다른 프로그래밍 언어에서는이 동작을 "메소드 해결 순서"또는 "MRO"라고도합니다.

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