当前位置: 首页 > 面试题库 >

Scala编译器未使用case类的unapply方法进行模式匹配,这是为什么?

陆宏扬
2023-03-14
问题内容
abstract class Animal

case class Cat(name: String) extends Animal

case class Dog(name: String) extends Animal

说我已经定义了猫和狗两个案例类。

然后我像这样使用它们:

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,则会得到如下信息:

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生成未应用的方法,但是在模式匹配代码中不会使用它们。

这是为什么?


问题答案:

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

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

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

8.1.6构造器模式

句法:

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

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

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

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



 类似资料:
  • 在一个actor中(这里我只是使用一个名为的常规对象,因为这个问题并不是akka特有的),我正在进行模式匹配并调用一个函数,该函数对我的有效负载类型进行操作。 由于我不理解的原因,使用和未应用的case类进行模式修补不会推断出的类型参数。在上面的代码中,我希望的类型为。但是,当我编译时,它认为类型是。 这是意料之中的行为吗?如果是的话,我对Scala中的类型推断有什么误解?

  • 主要内容:实例,实例,使用样例类,实例Scala 提供了强大的模式匹配机制,应用也非常广泛。 一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。 以下是一个简单的整型值模式匹配实例: 实例 object Test {     def main (args : Array [String ] ) {       println (matchTes

  • Scala 提供了强大的模式匹配机制,应用也非常广泛。 一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。 以下是一个简单的整型值模式匹配实例: object Test { def main(args: Array[String]) { println(matchTest(3))

  • 我有一个从提取的代码,对于多个子类来说,这个代码看起来应该完全相同,所以我尽量避免重复。但是,实际上(见下文),scala认为是一个泛型的,返回的值类型为,当然,它没有和方法。 问题是在这里避免重复的适当方法是什么?我对将转换为字符串并不那么着迷,因为这段代码可以使用刚从字符串解析为AST的json。我开始考虑为我需要的三种类型编写包装器,并将这些类型的匹配和隐式转换器转换为包装器,然后为这些包装

  • 我试图理解Scala代码如何在Java的IDE中与Java一起工作。我在使用Spark Java时遇到了这个疑问,在Spark Java中,我看到Scala包也在代码中,并且使用了相应的类和方法。 我的理解是,Scala代码需要Scala的编译器转换成Java.class文件,然后从它们开始JDK在JVM中完成它的部分,转换成二进制文件并执行操作。如果我说错了,请指正。 之后,在eclipse中的

  • 假设我们有一个泛型类: 然后,我们希望将与和的进行模式匹配: