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

时间:2018-05-15 12:20:35

标签: 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)
}

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

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

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

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

2 个答案:

答案 0 :(得分:6)

您的自定义 SELECT Cast(Convert(datetime,'15-05-2018 16:09:21',103) as datetime); SELECT convert( varchar(20),Convert(datetime,'15-05-2018 16:09:21',103) ,120) 与自动生成的unapply冲突,因为它具有相同的名称和相同的参数类型(只有返回类型不同)。因此,出于与

相同的原因,这是无效的
unapply

无效。此代码段会显示错误:

  

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

因此,您要么必须使用自己的class A { def u(i: Int): Int = i def u(i: Int): String = "int" + i } (类似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) } ,实施自己的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) } 。使用单独的提取器来使用多个unapply方法。

答案 1 :(得分:0)

这不是你问的问题,但是如果你想保留case class,你可以做以下事情:

case Person(firstName, lastName, _) =>

为您不使用的每个参数添加下划线_

请参阅https://scalafiddle.io/sf/HvxvdAZ/3