In scala 3, how instance of an opaque type can invoke method defined on its backed type

121 Views Asked by At

According to the book Advanced Programming in Scala 5th edition wrriten by Martin Ordersy

Note that adding an upper bound to an opaque type doesn’t act like the extends keyword does when defining a class. In particular, an opaque type does not inherit the interface of its upper bound. For example, although you can pass a NonEmptyString where a String is required, you cannot invoke methods declared on class String on a NonEmptyString:

object NonEmptyStrings:
  opaque type NonemptyString <: String = String
  object NonEmptyString:
    def apply(S: String): NonEmptyString = 
      require(s.nonEmpty)
      s
    def from(s: String): Option[NonEmptyString] = 
      if s.nonEmpty then Some(s) else None
……………………………………
// in a different .scala file
import NonEmptyStrings._
"hi".charAt(1) // i
NonEmptyString("hi").charAt(1)
1 |NonEmptyString("hi").charAt(1)
  |ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ
  |value charAt is not a member of
  |NonEmptyStrings.NonEmptyString

The only methods you will be able to invoke on an opaque type are those defined on Any and those added via any extension methods defined for the opaque type, even if the opaque type is given an upper bound

But when I coded like that, no exception occured.The NonEmptyString("hi").charAt(1) runned normally and the result can be printed to i

But when I code like that, no exception occured.The NonEmptyString("hi").charAt(1) run normally and the result can println into console showing i.

My practice is not like the book predicted.

1

There are 1 best solutions below

0
On

After a short discussion with one of the book's authors, I confirm this is incorrect or outdated, and should be fixed in the next edition.