unapply method of a case class is not used by the Scala compiler to do pattern matching, why is that?

后端 未结 2 967
执念已碎
执念已碎 2021-01-14 06:25
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

相关标签:
2条回答
  • 2021-01-14 06:52

    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.

    0 讨论(0)
  • 2021-01-14 07:04

    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
    
    0 讨论(0)
提交回复
热议问题