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
をパラメータ化することができますUnforunately
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
}
、あなたは二回FooImpl1
を書く必要はなく、自己のタイプは、まだ二つの異なる実装を混入を防ぎます。
代わりにFoo
に型メンバーを使用することです。 SpecialFoo
を作成するときに実装タイプを2回指定する必要はありませんが、実装自体を作成して正しいタイプをバインドする場合は、実装タイプを2回指定する必要はありません。
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
F-囲ま作るすなわちtrait Foo[A <: Foo]
、上記の例に似た何かをすることができます。
BTWシャドーイング「this」は良い考えではありません – cchantep