2013-01-05 5 views
6

나는 그것에 대해 정의 된 몇 가지 스태킹 특성을 가진 추상 기본 클래스 (Base)가 있습니다 (StackingTrait).스칼라 : 추상 기본 클래스가있는 Trait Mixin

trait Base { 
    def foo 
} 
trait StackingTrait extends Base { 
    abstract override def foo { super.foo } 
} 

다음과 같은 구문을 사용하여 서브 클래스를 구현하기가 매우 편리 할 것이다, 그러나 컴파일러는 foo는 다음 override와 함께 선언 할 필요가 있다고하기 때문에이 작동하지 않기 때문에 유효 재 컴파일에 abstract overrideImpl은 수업입니다.

class Impl extends Base with StackingTrait { 
    def foo {} 
} 

그런 구문이 허용되지 않는 이유에 대해서는 생각할 수 없습니다. foo는 논리적으로 Impl으로 정의되므로 개념적으로 스태킹 순서가 동일하게 유지됩니다.

참고 : 내가 원하는 것과 동일한 효과를 발휘할 수있는이 해결 방법을 알았지 만 도우미 클래스의 필요성으로 인해 더 나은 해결책을 원합니다.

class ImplHelper extends Base { 
    def foo {} 
} 
class Impl extends ImplHelper with StackingTrait 

왜 원하는 구문이 컴파일되지 않고 우아한 해결책이 있습니까?

답변

4

제 이해는 오류 메시지가 혼동을 줄 수 있지만 동작이 올바른 것입니다. fooStackingTrait에서 abstract override로 선언하고, 따라서 StackingTrait 전에 (안 abstract로 표시) 구체적인 foo의 구현이 있어야 혼합 어떤 구체적인 클래스 (선형화 순서를 기준으로) StackingTrait. 이는 super이 직선화 순서로 직전의 특성을 참조하기 때문에 이 혼합되기 전에 반드시 foo의 구체적인 구현이되어야하거나 super.foo이 무의미하기 때문입니다. 이 작업을 수행 할 때

: - StackingTrait <-Impl

class Impl extends Base with StackingTrait { 
    def foo {} 
} 

선형화 순서는 Base <입니다. StackingTrait 이전의 유일한 특성은 Base이고 Basefoo의 구체적인 구현을 정의하지 않습니다. ImplHelperfoo의 구체적인 정의를 포함하고 여기에 ImplStackingTrait 전에 definitly 입니다 - ImplHelper < - - StackingTrait < Base을 < :이 작업을 수행 할 때

는하지만 :

traitImplHelper extends Base { 
    def foo {} 
} 
class Impl extends ImplHelper with StackingTrait 

선형화 순서가된다.

StackingTrait (class Impl extends StackingTrait with ImplHelper과 같이) 뒤에 ImplHelper을 섞어 쓰면 다시 같은 문제가 발생하며 컴파일에 실패하게됩니다.

그래서이 모양은 나에게 상당히 일치합니다. 의도대로 컴파일하는 방법을 모르겠습니다.그러나 Base 또는 StackingTrait을 쉽게 쓰는 것보다 Impl (더 쉽게 별도의 클래스/특성을 필요로하지 않고 foo을 정의 할 수 있음)을 작성하는 것이 더 염려되는 경우에도 다음을 수행 할 수 있습니다.

trait Base { 
    protected def fooImpl 
    def foo { fooImpl } 
} 
trait StackingTrait extends Base { 
    abstract override def foo { super.foo } 
} 

class Impl extends Base with StackingTrait { 
    protected def fooImpl {} 
} 
원래 버전에 당신이 (fooImpl의 형태로) foo을 구현하기 위해 각각의 구체적인 클래스를 강제 것처럼

하고 컴파일 않는이 시간. 여기에 단점은 fooImplsuper.foo을 호출하면 안되며 (이는 의미가 없으며 무한 루프가됩니다) 컴파일러는 경고하지 않는다는 것입니다.

+0

위대한 답변! 나는 바로이 시나리오에 관한 질문을 올리려고했다. 감사! –

+0

방금이 문제가 발생했습니다. 선형화는 궁극적으로 이것에 대해 옳았지 만, 형질을 쌓는 실제 목적은 다음과 같습니다. 스태킹 특성을 사용하여 일반적인 추상 클래스/특성의 기존 구체 구현에만 수정할 수 있습니다. 예. 'abstract class List'와'Mod Mod extends List'를 가지고 있습니다. 'class Foo extends Mod with List'라고 쓸 수는 없습니다. 먼저'LinkedList extends List' 클래스와 같이 구체적인 List를 가져야합니다. 그런 다음'Class Bar extends Moded with LinkedList '를 작성할 수 있습니다. 희망은 그 말이 맞습니다. –

+0

나는 이것이 추상적 인 오버라이드 (abstract override) 메쏘드를 가진 형질에만 관심이 있다는 것을 잊어 버렸다. 그러한 방법이 없으면 형질이 자유롭게 혼합 될 수 있습니다. –