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
Language. Methods in Scala can be parameterized by type as well as value. The syntax is similar to that of generic classes. Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses.
If we want the data to be of int type, the T can be replaced with Integer, and similarly for String, Character, Float, or any user-defined type. The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section.
Scala is a statically typed programming language. This means the compiler determines the type of a variable at compile time. Type declaration is a Scala feature that enables us to declare our own types.
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With