I would like to define a trait with a method that returns a generic type value and then define a class hierarchy where a parent class defines a specific generic type value and the subclass defines a different one, like so:
trait Thingy {
type T
def doIt(): T
}
class A extends Thingy {
override type T = Array[Int]
override def doIt(): T = {
Array[Int](1, 2, 3)
}
}
class B extends A {
override type T = Array[String]
def doIt(): T = {
Array[String]("stringy")
}
}
val aa = new A()
println(aa.doIt().length)
val bb = new B()
println(bb.doIt()(0))
This generates compile errors
ScalaFiddle.scala:16: error: overriding type T in class A, which equals scala.this.Array[scala.this.Int];
type T has incompatible type;
found : B.this.T
(which expands to) scala.this.Array[String]
required: A.this.T
(which expands to) scala.this.Array[scala.this.Int]
override type T = Array[String]
^
ScalaFiddle.scala:17: error: overriding method doIt in class A of type ()B.this.T;
method doIt needs `override' modifier;
found : ()B.this.T
(which expands to) ()scala.this.Array[String]
required: ()A.this.T
(which expands to) ()scala.this.Array[scala.this.Int]
def doIt(): T = {
^
I have tried parameterized types, abstract classes, and traits but I can't seem to get it right. Can someone explain if there is a way to do it?
Adding use case to answer Luis Miguel Mejía Suárez
I'm simply trying to use inheritance to inherit common methods while maintaining 2 different data structures to represent the internal state of each class. Say the parent class is a Grid that represents its internal data structure with a 2D Array of Cells of known dimensions
class Grid(var rows, var columns) {
protected var _grid: Array[Array[Cell]] = makeGrid()
def makeGrid(): Array[Array[Cell]] = {
var g = Array.ofDim[Cell](rows, columns)
// populate g
g
}
}
and I have a subclass that needs to represent the grid with a mutable ArrayBuffer:
class OtherGrid(var rows) extends Grid(rows, 1) {
protected var _grid: ArrayBuffer[ArrayBuffer[Cell]] = makeGrid()
override def makeGrid(): ArrayBuffer[ArrayBuffer[Cell]] = {
// initialize and populate the grid
}
}
Is this the wrong way to go about things in a functional programming language?