15
votes

I'm trying to create a generic trait which has a method that returns an instance of the class itself. For example:

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

Without explicit return 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

This fails compilation because the return value of the implemented withData is SomeImpl but the expected return type based on the trait's method declaration is SomeImpl.this.type.

Does anyone know how I need to change the return type of the trait method declaration so this will work? The more general use case I have is a way to expose a case class' copy method through a generic trait it extends. I know I may not be articulating this clearly, let me know if I should clarify anything.

Using Scala 2.10.0

1

1 Answers

12
votes

You can solve it by parameterizing the trait with type type of class you're mixing into:

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 is a singleton type - the type of one specific instantiated SomeGenericTrait.