Is there a better explanation than "this is how it works". I mean I tried this one:
class TestShortMatch[T <: AnyRef] {
def foo(t: T): Unit = {
val f = (_: Any) match {
case Val(t) => println(t)
case Sup(l) => println(l)
}
}
class Val(t: T)
class Sup(l: Number)
}
and compiler complaints:
Cannot resolve symbol 'Val'
Cannot resolve symbol 'Sup'
Of course if I add case before each of the classes it will work fine. But what is the reason? Does compiler make some optimization and generate a specific byte-code?
The reason is twofold. Pattern matching is just syntactic sugar for using extractors and case classes happen to give you a couple methods for free, one of which is an extractor method that corresponds to the main constructor.
If you want your example above to work, you need to define an unapply method inside objects Val and Sup. To do that you'd need extractor methods (which are only defined on val fields, so you'll have to make your fields vals):
class Val[T](val t: T)
class Sup(val l: Number)
object Val {
def unapply[T](v: Val[T]): Option[T] = Some(v.t)
}
object Sup {
def unapply(s: Sup): Option[Number] = Some(s.l)
}
And which point you can do something like val Val(v) = new Val("hi"). More often than not, though, it is better to make your class a case class. Then, the only times you should be defining extra extractors.
The usual example (to which I can't seem to find a reference) is coordinates:
case class Coordinate(x: Double, val: Double)
And then you can define a custom extractors like
object Polar {
def unapply(c: Coordinate): Option[(Double,Double)] = {...}
}
object Cartesian {
def unapply(c: Coordinate): Option[(Double,Double)] = Some((c.x,c.y))
}
to convert to the two different representations, all when you pattern match.
You can use pattern matching on arbitrary classes, but you need to implement an unapply method, used to "de-construct" the object.
With a case class, the unapply method is automatically generated by the compiler, so you don't need to implement it yourself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With