I would like to have a sealed trait which have a declared method that returns the actual class that extends the trait. Should I use an abstract type, a parameter type or is there any other nice way to solve this?
sealed trait Foo {
type T
def doit(other: T): T
}
or
sealed trait Foo[T] {
def doit(other: T): T
}
Note that T
must be a subtype of Foo
in this example. If I do it like this the type
information feels too repeated:
case class Bar(name: String) extends Foo[Bar] {
def doit(other: Bar): Bar = ...
}
They are mostly interchangeable. According to Odersky, the reason was mainly for completeness: That similarly to the fact that methods and fields (values) can be either abstract or passed as parameters, so can types.
It is better to use an abstract type when you intend to mix several traits that all use the same type name. With type parameters you need to explicitly pass the type to each
Here's an article explaining all of this: http://www.artima.com/weblogs/viewpost.jsp?thread=270195
You can cut down on the repetition somewhat by having your doit
method return a factory function:
trait Foo[T] {
self: T =>
def doit: T => T
}
case class Bar(name: String) extends Foo[Bar] {
// note: types omitted
def doit = { other => Bar(name + other.name) }
}
It's not possible to do the same with an abstract type:
trait Foo {
self: T => // won't compile because T isn't defined yet
type T
def doit: T => T
}
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