Reputation: 4794
Consider the following code:
sealed trait SpecieType
case class Mammal() extends SpecieType
case class Insect() extends SpecieType
abstract class Specie(name: String, specie: T) {
type T <: SpecieType
}
However this fails to compile (line 5) because the abstract type is defined inside Specie
class definition.
What do I need to change to make this work?
The reason why I needed an abstract type is because I need the type of its parameter at compile time (to perform implicit lookups for typeclass pattern). Basically, I need to do something like this: implicitly[SomeTypeClass[Specie#T]]
, where SomeTypeClass
is a typeclass that all subclass of SpecieType
implements.
Upvotes: 0
Views: 132
Reputation: 22085
Unfortunately, this is one of the cases where the class body as constructor creates severe limitations. What you're trying to achieve is impossible per se.
To the best of my knowledge, there are two main alternatives. One is, as suggested by @cchantep in a comment, to use a type parameter instead of an abstract type member. The caveat is that it changes the declaration of Specie
, which might make your life tedious in the rest of the program.
The other alternative allows you to retain the type member version at the expense of a bit of unsafety. This might be acceptable because you have an abstract class anyway, so only subclasses need to be careful:
sealed abstract class Specie(name: String, _specie: SpecieType) {
type T <: SpecieType
val specie: T = _specie.asInstanceOf[T]
}
class MammalSpecie extends Specie("Mammal", Mammal()) {
type T = Mammal
}
You can re-enforce safety if you can bear to uglify the definition of subclasses of Specie
, using an intermediate abstract class:
sealed abstract class Specie(name: String, _specie: SpecieType) {
type T <: SpecieType
val specie: T = _specie.asInstanceOf[T]
}
abstract class SpecieBase[U <: SpecieType](name: String, _specie: U)
extends Specie(name, _specie) {
type T = U
}
class MammalSpecie extends SpecieBase("Mammal", Mammal())
Since Specie
itself is sealed, the only way to extend from Specie
is to actually extend from SpecieBase
, which is not sealed. SpecieBase
enforces the safety that Specie
cannot enforce itself.
Upvotes: 2