2017-01-03 12 views
1

自己型付けされた特性内のScalaで具体的な型の注釈を参照したいと思います。具体的な自己型を取得するスカラ

私は 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をパラメータ化することができます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]、上記の例に似た何かをすることができます。

関連する問題