案例类的自定义提取器在模式匹配中不起作用

Kum*_*ode 3 scala

考虑一个案例类Person

case class Person(firstName: String, lastName: String, middleName: Option[String])

object Person {

def apply(firstName: String, lastName: String): Person = new Person(firstName, lastName, None)

def unapply(arg: Person): Option[(String, String)] = Some(arg.firstName, arg.lastName)
}

 val person = Person("firstName", "lastName")

 person match {
case Person(firstName, lastName) => Console.println(firstName + " " + lastName)
}
Run Code Online (Sandbox Code Playgroud)

在与case类编译器的模式匹配中给出了一个错误:模式匹配中的参数数量错误,但是当我使用类而不是case类时它的工作.

class Person(val firstName: String, val lastName: String, middleName: Option[String])
Run Code Online (Sandbox Code Playgroud)

我在这里理解的是,我们不能为case类使用自己的自定义提取器,但可以使用自己的构造函数(apply).请解释我这种奇怪的行为.

这是一个测试的ScalaFiddle:https://scalafiddle.io/sf/HvxvdAZ/0

And*_*kin 6

您的自定义unapply与自动生成的冲突unapply因为它具有相同的名称和相同的参数类型(只有返回类型不同).所以,由于同样的原因,这是无效的

class A {
  def u(i: Int): Int = i
  def u(i: Int): String = "int" + i
}
Run Code Online (Sandbox Code Playgroud)

会无效的.此代码段会给出错误:

错误:方法u定义两次; 你在第12:7行定义了冲突的方法

因此,您要么必须使用自己的unapply(类似的object FirstLast { def unapply(...) ... })定义单独的提取器对象,要么省略case类声明中的提取器对象.

单独的提取器对象

这是一个(在我看来相对优雅)的方式:

case class Person(
  firstName: String, 
  lastName: String, 
  middleName: Option[String]
)

object Person {

  def apply(
    firstName: String, 
    lastName: String
  ): Person = new Person(firstName, lastName, None)

  object FirstLast {
    def unapply(arg: Person): Option[(String, String)] = 
      Some((arg.firstName, arg.lastName))
  }
}

val person = Person("firstName", "lastName")
person match {
  case Person.FirstLast(firstName, lastName) => 
    Console.println(firstName + " " + lastName)
}
Run Code Online (Sandbox Code Playgroud)

省略case,实施自己的unapply

如果您想完全替换原件unapply,那么您可以这样做:

class Person(
  val firstName: String, 
  val lastName: String, 
  val middleName: Option[String]
)

object Person {

  def apply(
    firstName: String, 
    lastName: String, 
    middleName: Option[String]
  ): Person = new Person(firstName, lastName, middleName)

  def apply(
    firstName: String, 
    lastName: String
  ): Person = new Person(firstName, lastName, None)

  def unapply(arg: Person): Option[(String, String)] = 
    Some((arg.firstName, arg.lastName))
}

val person = Person("firstName", "lastName")
person match {
  case Person(firstName, lastName) => 
    Console.println(firstName + " " + lastName)
}
Run Code Online (Sandbox Code Playgroud)

但同样,它只允许一个单一unapply.使用单独的提取器来使用多个unapply方法.