abstract class Animal
case class Cat(name: String) extends Animal
case class Dog(name: String) extends Animal
Say I have defined Cat and Dog, two
Looking at this question from the point of view of the Scala language, the implementation works as specification requires. See http://www.scala-lang.org/docu/files/ScalaReference.pdf
In §5.3.2, case classes are defined to include an implementation of unapply in the companion (extractor) object.
However, when we get to pattern matching (§8.1), case classes have their own section on matching, §8.1.6, which specifies their behaviour in pattern matching based on the parameters to the constructor, without any reference to the already-generated unapply/unapplySeq:
8.1.6 Constructor Patterns
Syntax:
SimplePattern ::= StableId ‘(’ [Patterns] ‘)
A constructor pattern is of the form c(p1,…,pn) where n≥0. It consists of a stable identifier c, followed by element patterns p1,…,pn. The constructor c is a simple or qualified name which denotes a case class. If the case class is monomorphic, then it must conform to the expected type of the pattern, and the formal parameter types of x's primary constructor are taken as the expected types of the element patterns p1,…,pn. If the case class is polymorphic, then its type parameters are instantiated so that the instantiation of c conforms to the expected type of the pattern. The instantiated formal parameter types of c's primary constructor are then taken as the expected types of the component patterns p1,…,pn. The pattern matches all objects created from constructor invocations c(v1,…,vn) where each element pattern pi matches the corresponding value vi.
The document continues to describe the use of unapply/unapplySeq in §8.1.8; but this is a separate, disjoint, part of the specification, which is applied for classes which are not case classes.
So you can consider unapply to be a useful method to use in your own code, but not something that is required by pattern matching inside the scala language.
My guess is that this is an optimisation scalac performs. The unapply
method is synthetic, so the compiler knows its implementation and might improve on the runtime performance.
If that theory is correct, the following should be different:
object Cat {
def unapply(c: Cat): Option[String] = Some(c.name)
}
class Cat(val name: String) extends Animal