I wanted to extend the logarithmic representation example from the Scala3 book (here: Opaque Types | Scala 3 — Book | Scala Documentation ) with toString:
object Logarithms: //vvvvvv this is the important difference! opaque type Logarithm = Double object Logarithm: def apply(d: Double): Logarithm = math.log(d) extension (x: Logarithm) def toDouble: Double = math.exp(x) def + (y: Logarithm): Logarithm = x + math.log1p(math.exp(y-x)) def * (y: Logarithm): Logarithm = x + y // vvvvvvvvv these two do not work! //def toString: String = "log:"+x.asInstanceOf[Logarithm].toDouble.toString def toString2: String = "log:"+x.asInstanceOf[Logarithm].toDouble.toString //def toString2a: String = "log:"+x.toDouble.toString // this works, but this is not what I want def toDouble2: Double = math.exp(x) def toString3: String = "log:"+x.toDouble2.toString // this does not work: //def toString: String = "log:"+x.toDouble2.toString
It looks like method overriding does not work:
$ ~/Downloads/scala3-3.1.3/bin/scala Welcome to Scala 3.1.3 (14.0.1, Java OpenJDK 64-Bit Server VM). Type in expressions for evaluation. Or try :help. scala> :load my/scala/logarithms.scala // defined object Logarithms scala> import Logarithms.* scala> Logarithm(4) val res0: Logarithms.Logarithm = 1.3862943611198906 scala> Logarithm(4).toString val res1: String = 1.3862943611198906 // expected: log:4.0 scala> Logarithm(4).toDouble.toString val res2: String = 4.0 scala> Logarithm(4).toString2 val res3: String = log:1.3862943611198906 // expected: log:4.0 scala> Logarithm(4).toString3 val res4: String = log:4.0 // as expected, but there is no overriding: toDouble2 and toString3 !
It looks like one or two bugs. Or a leaky abstraction.
Or may be there is some syntax not covered in the Scala-3 book.