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.