2013-11-23 3 views
11

私は、クラス自体のインスタンスを返すメソッドを持つジェネリック特性を作成しようとしています。明示的な戻り値の型なしスカラジェネリックthis.type

trait SomeGenericTrait[T]{ 
    def withData(newData : Seq[T]) : this.type 
} 

case class SomeImpl(data : Seq[Int]) extends SomeGenericTrait[Int] { 
    override def withData(newData : Seq[Int]) : SomeImpl = copy(data = newData) 
} 

error: overriding method withData in trait SomeGenericTrait of type(newData: Seq[Int])SomeImpl.this.type; method withData has incompatible type 

:たとえば実装withDataの戻り値がSomeImplですが、トレイトのメソッド宣言に基づいて予想される戻り値の型がSomeImpl.this.typeあるので

case class SomeImpl(data : Seq[Int]) extends SomeGenericTrait[Int] { 
    override def withData(newData : Seq[Int]) = copy(data = newData) 
} 

error: type mismatch; 
found : SomeImpl 
required: SomeImpl.this.type 

これはコンパイルに失敗します。

これは機能するように私はtraitメソッド宣言の戻り値の型を変更する必要がどのように知っていますか?私が持っているより一般的な使用例は、ケースクラスのcopyメソッドを拡張する一般的な特性を通して公開する方法です。私はこれを明確に明言していない可能性があることを知っている、私は何かを明確にすべきかどうか私に知らせる。 - 特定のものの種類

trait SomeGenericTrait[T, X] { 
    def withData(newData: Seq[T]): X 
} 

case class SomeImpl(data: Seq[Int]) extends SomeGenericTrait[Int, SomeImpl] { 
    override def withData(newData: Seq[Int]): SomeImpl = copy(data = newData) 
} 

this.typeはシングルトンタイプである:Scalaの2.10.0

答えて

10

を使用して

あなたが混入しているクラスの型の種類と特性をパラメータ化することによってそれを解決することができますSomeGenericTraitをインスタンス化しました。

+1

(このパターンは[CRTP](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern#In_other_languages)として知られています) – Rich

+0

つまり、 'this.type'は' this'だけを返すことができますが、 'copy'で作成された同じクラスの新しいインスタンスを返すことはできません。 –

+0

もう少し厳密な宣言は、Xをその形質のサブクラスに限定する 'trait SomeGenericTrait [T、+ X <:SomeGenericTrait [T、X]]'となります。 –

関連する問題