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-경계 확인하고 위의 예와 비슷한 뭔가를 할 수 있습니다.
BTW 섀도 잉 'this'는 좋은 생각이 아닙니다. – cchantep