2017-01-03 6 views
1

자체 유형 특성 내에서 스칼라의 자체 유형 주석의 구체 유형에 대한 참조를 얻고 싶습니다. 나는 이런 일이 : 나는 new FooImpl1 with SpecialFoo을 할 경우, 내가 필요로 (FooImpl1의 또는 하위 유형)을 FooImpl1를 반환하는 |+| 방법을 싶습니다스칼라가 자체 유형의 구체적인 유형 가져 오기

trait Foo 
class FooImpl1 extends Foo 
class FooImpl2 extends Foo 

trait SpecialFoo { 
    this:Foo => 

    def |+|(that:this.type):this.type // the type signature is incorrect here 
} 

. 그러나 위 코드를 사용하면 SpecialFoo.this.type을 원하는 것처럼 보이는데 이는 놀랄 일이 아니지만 원하는 것은 아닙니다.

+0

BTW 섀도 잉 'this'는 좋은 생각이 아닙니다. – cchantep

답변

0

this.type은 어떤 경우 든 SpecialFoo의 싱글 톤 유형입니다. 정의 된대로 |+|은 자체적으로 호출 할 수 있습니다. 예를 들어 :

trait Spec { def |+|(that: this.type): this.type = that } 
val s = new Spec {} 
val s2 = new Spec {} 

scala> s |+| s 
res1: <refinement>.type = [email protected] 

scala> s |+| s2 
<console>:14: error: type mismatch; 
found : Spec 
required: <refinement>.type 
     s |+| s2 
      ^

this.type어떤 경우에는FooImpl1이지만, 컴파일러는 것을 알 수있는 방법이 없습니다. 더 세련된 유형 인 FooImpl1 또는 FooImpl2을 캡처 할 방법이 필요합니다. 자기 유형 this: Foo =>만이 Foo 인 것으로 알고 있습니다. 두 가지 가능성이 있지만 둘 다 좋아 보이지 않을 것입니다.

당신은 SpecialFoo을 매개 변수화 할 수 있습니다

trait Foo 
class FooImpl1 extends Foo 
class FooImpl2 extends Foo 

trait SpecialFoo[A <: Foo] { self: A => 
    def |+|(that: A): A 
} 

val foo = new FooImpl1 with SpecialFoo[FooImpl1] { 
    def |+|(that: FooImpl1): FooImpl1 = that 
} 

는 Unforunately, 당신은 두 번 FooImpl1를 작성해야하지만 자기 형은 여전히 ​​두 개의 서로 다른 구현을 혼합에서 당신을 방지 할 수 있습니다.

대체 방법은 Foo 내에 형식 멤버를 사용하는 것입니다. SpecialFoo을 만들 때 구현 유형을 두 번 지정할 필요는 없지만 올바른 유형을 바인딩하기 위해 구현 자체를 만들 때 수행해야합니다.

trait Foo { type S } 
class FooImpl1 extends Foo { type S = FooImpl1 } 
class FooImpl2 extends Foo { type S = FooImpl2 } 

trait SpecialFoo { self: Foo => 
    def |+|(that: self.S): self.S 
} 

val foo = new FooImpl1 with SpecialFoo { 
    def |+|(that: FooImpl1): FooImpl1 = that 
} 

또한 Foo가, 즉 trait Foo[A <: Foo]을 F-경계 확인하고 위의 예와 비슷한 뭔가를 할 수 있습니다.