Reputation: 65
So I have been working on a refactor in my project to convert Vector
's in my code to Array
's. The reason being that my application needs to be very performant, and using while-iterations on Array
's is significantly faster than for comprehensions and iterations on Vector
's. (see this blog post for details)
However I have run into an issue I can't seem to easily find an answer for. I have tweaked my code to hide implementation details, and just boil down to the code needed to highlight the issue.
The following class structure, when using Vector
, compiles totally fine:
sealed abstract class BaseClass {
def element: Int
}
sealed abstract class TypeA extends BaseClass {
def element = 2
def children: Vector[BaseClass]
}
case class TypeB(element: Int = 2) extends BaseClass
case class TypeAA(children: Vector[TypeA]) extends TypeA
case class TypeAB(children: Vector[TypeB]) extends TypeA
Now, when switching from using Vector
to using Array
, it no longer compiles:
sealed abstract class BaseClass {
def element: Int
}
sealed abstract class TypeA extends BaseClass {
def element = 2
def children: Array[BaseClass]
}
case class TypeB(element: Int = 2) extends BaseClass
case class TypeAA(children: Array[TypeA]) extends TypeA
case class TypeAB(children: Array[TypeB]) extends TypeA
I get the error: overriding method children in class TypeA of type => Array[BaseClass]; value children has incompatible type
for both TypeAA and TypeAB classes.
I have a feeling I need to do an implicit conversion somewhere, but I am relatively new to Scala (only a couple months) and am not sure exactly how to use it.
Sorry if this has been asked elsewhere, I had trouble finding the correct search terms for the issue i am having.
Upvotes: 2
Views: 133
Reputation: 149518
This comes from the fact Vector[+A]
is covariant in its type parameter A
while Array[A]
is not, meaning invariant in A
You can work around that fact using F-Bounded Polymorphism:
sealed abstract class TypeA[A :< Type[A]] extends BaseClass {
def children: Array[A]
}
case class TypeAA(children: Array[TypeA]) extends TypeA[TypeA]
case class TypeAB(children: Array[TypeB]) extends TypeA[TypeB]
Upvotes: 1
Reputation: 2480
I think you need to use _ <: BaseClass
instead of using the generic type itself:
sealed abstract class TypeA extends BaseClass {
def element = 2
def children: Array[_ <: BaseClass]
}
This happens because the generic type parameter in Array
is invariant, while in Vector
it is covariant:
final class Array[T]
final class Vector[+A]
Hope that helps you.
Upvotes: 3