There's a common Java idiom (seen in Enum
for example) to declare a generic type variable that has to match the actual derived type.
class Enum<E extends Enum<E>> {
...
}
or, if needed more generic arguments:
abstract class Foo<T, Actual extends Foo<T, Actual>> {
//now we can refer to the actual type
abstract Actual copy();
}
class Concrete<T> extends Foo<T, Concrete<T>> {
Concrete<T> copy() {...}
}
Things can get very verbose really quickly, so I imagined that Scala might have something nicer than a literal translation of the examples above.
Are there any more elegant ways to achieve this?
An alternative formulation is to use abstract type members:
trait Foo { self =>
type A <: Foo {type A = self.A}
}
With your example:
trait Foo { self =>
type T
type Actual <: Foo {type T = self.T; type Actual = self.Actual}
}
trait Concrete extends Foo { self =>
type T
type Actual = Concrete {type T = self.T}
}
While this reformulation isn't really nicer at the trait/class declarations, when using the traits/classes it can be much terser. (And as far as I know, there isn't another way to reformulate recursive types).
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