Beginner question. I have a minimal List implementation:
sealed trait MyList[+A]
case object Nil extends MyList[Nothing]
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A]
object MyList {
def apply[A](as: A*): MyList[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
private def toString(l: MyList[Any]): String = {
def f(l: MyList[Any]): String = {
l match {
case Nil => "]"
case Cons(x, Nil) => x.toString + "]"
case Cons(x, xs) => x.toString + ", " + f(xs)
}
}
"[" + f(l)
}
def main(args: Array[String]): Unit = {
println(toString(MyList(1, 2, 3)))
}
}
The output of this program is [1, 2, 3]
. Is it possible to get the same output without explicitly calling the private method toString()
? That is, to make this the default print output when calling println.
I have tried to add this overriding method:
override def toString: String = ...
But I ran into two problems. The first is that it's not actually affecting the output of println
, no matter what this overriding method returns (even though println
ultimately calls toString
). The second is that I don't know how to print the list content without a parameter for the list itself (toString
does not take any parameters, so I assume it must reference this
, or something else?).
object MyList
and trait MyList
are 2 different classes in runtime, so whether you put toString
in one or the other changes what will be overriden
sealed trait MyList[+A] {
override def toString = "x"
}
case object Nil extends MyList[Nothing]
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A]
object MyList {
// ...
override def toString = "y"
}
println(Nil)
println(Cons("string", Nil))
println(MyList)
Additionally case class
/case object
creates its own override def toString
by default so if you want to override toString
in both Nil
and Cons
I would suggest putting final
before override def toString
in sealed trait MyList[+A]
to make sure it is respected.