SCALA - Curly brackets in subtype declarations

Viewed 87

In the following code,

trait SwingApi {

    type ValueChanged <: Event

    val ValueChanged: {
       def unapply(x: Event): Option[TextField]
    }

    type ButtonClicked <: Event

    val ButtonClicked: {
        def unapply(x: Event): Option[Button]
    }

    type TextField <: {
        def text: String
        def subscribe(r: Reaction): Unit
        def unsubscribe(r: Reaction): Unit
    }

    type Button <: {
        def subscribe(r: Reaction): Unit
        def unsubscribe(r: Reaction): Unit
    }

}

Can someone please explain to me, what we mean by

    val ValueChanged: {
       def unapply(x: Event): Option[TextField]
    }

and

    val ButtonClicked: {
        def unapply(x: Event): Option[Button]
    }

What's the name for this pattern so that I can search for more details on Google.

1 Answers

Those things in curly braces are structural types. Nominal typing (which Scala usually uses) is when two types are equal if their names match. Structural typing is when two types are considered equal if their contents match.

A structural type like this means that buttonClicked is of some type that has an unapply method with the given signature. It does not matter what type that is, what its name is, just that it has that method, so that we can call the unapply method.

{
  def unapply(x: Event): Option[Button]
}

You can also refine a nominal or compound type. For example, if you want buttonClicked to be a String and an Int with an unapply method, it would be written like this:

String with Int {
  def unapply(x: Event): Option[Button]
}

Structural types are usually not recommended, mainly because the JVM does not support them. Because of this, the compiler generates code that uses reflection to access unapply or whatever other methods you have in your structural type. isInstanceOf, asInstanceOf, and pattern matching also don't work with structural types, since they're erased, so you can find yourself in a situation where your code compiles but there's an error at runtime because a method doesn't exist.

Scala 3 may bring safer programmatic structural types.

Related