Scala编译器未使用case类的unapply方法进行模式匹配,这是为什么? [英] unapply method of a case class is not used by the Scala compiler to do pattern matching, why is that?

查看:92
本文介绍了Scala编译器未使用case类的unapply方法进行模式匹配,这是为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 case classes.

然后我像这样使用它们:

Then I use them like this:

val animal = createAnimal
animal match {
  case Dog(anyName) => "this is a dog"
  case Cat("kitty") => "this is a cat named kitty"
  case _ => "other animal"
}

如果我将字节码反编译为Java,我会得到类似

If I decompile the bytecode to Java, I get something like this:

Animal animal = createAnimal();
String result = "other animal";

if (animal instanceof Dog) {
    result = "this is a dog";
} else if (animal instanceof Cat) {
    Cat cat = (Cat) animal;
    if (cat.name() == "kitty") {
        result = "this is a cat named kitty";
    }
}

return result;

编译器同时为Cat和Dog生成未应用的方法,但是在模式匹配代码中未使用它们。

The compiler generates unapply methods for both Cat and Dog, but they are not used in the pattern matching code.

为什么?

推荐答案

从从Scala语言的角度来看,实现按规范要求工作。参见 http://www.scala-lang.org/docu/files/ScalaReference .pdf

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

在第5.3.2节中,案例类被定义为在伴随(提取器)对象中包含unapply的实现。

In §5.3.2, case classes are defined to include an implementation of unapply in the companion (extractor) object.

但是,当我们进行模式匹配(第8.1节)时,案例类在第8.1.6节中有其自己的匹配节,该节根据构造函数的参数指定其在模式匹配中的行为,而无需任何引用生成的unapply / unapplySeq:

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构造函数模式

8.1.6 Constructor Patterns

语法:

SimplePattern :: = StableId'('[Patterns]')

SimplePattern ::= StableId ‘(’ [Patterns] ‘)

构造函数模式的形式为c(p1,…,pn),其中n≥0。它由一个稳定的标识符c组成,后跟元素模式p1,…,pn。构造函数c是表示案例类的简单名称或限定名称。如果case类是单态的,则它必须符合模式的预期类型,并且x的主要构造函数的形式参数类型将作为元素模式p1,…,pn的预期类型。如果case类是多态的,则实例化其类型参数,以使c的实例符合模式的预期类型。然后,将c的主要构造函数的实例化形式参数类型作为组件模式p1,...,pn的预期类型。该模式匹配从构造函数调用c(v1,…,vn)创建的所有对象,其中每个元素模式pi都匹配对应的值vi。

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.

文档继续描述第8.1.8节中unapply / unapplySeq的使用;但这是规范的一个单独的,不相交的部分,适用于非案例类的类。

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.

因此,您可以认为unapply是一个有用的方法,可以自己使用代码,但不是Scala语言内部的模式匹配所必需的。

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.

这篇关于Scala编译器未使用case类的unapply方法进行模式匹配,这是为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆