模式匹配和部分函数中的unapply函数有什么区别

时间:2017-09-29 11:58:23

标签: scala pattern-matching

我有一个从字符串中提取对象的提取器。

case class ItemStructure(id: String, data: String)
object ItemStructure {
  def unapply(str: String): Option[ItemStructure] = {
    str.split('-').toList match {
      case List(id, data) => Some(ItemStructure(id, data))
      case _              => None
    }
  }
}

如果我尝试在模式匹配中使用此提取器,则所有提取器都按预期工作。

"" match {
  case ItemStructure(item) =>
}

它也适用于匹配匿名函数的模式。

Option("").map {
  case ItemStructure(item) => 
}

现在,如果我尝试在部分函数中使用此提取器,编译器将失败并显示以下消息:无法解析重载的unapply

val func: PartialFunction[Any, Unit] = {
  case ItemStructure(item) =>
}  

如果我重命名unapply函数所在的伴随对象,则所有对象都按预期工作。

有人可以解释为什么如果提取物位于伴侣对象中,它不起作用吗?

2 个答案:

答案 0 :(得分:4)

有两种ItemStructure.unapply方法:由case类创建的方法和您自己创建的方法。前者采用ItemStructure类型的参数,后者采用String类型的参数。

在前两个示例中,匹配对象的类型为String,因此只能应用第二个unapply方法,并且不存在歧义。但在最后一个示例中,两个unapply方法都符合条件,因此Scala不知道使用哪个方法。

如果您将unapply方法放在除了伴随对象之外的其他位置,则不再有两个unapply方法 - 只有您自己的方法(因为另一个方法仍然存在于伴随对象中)。这样可以解决歧义:ItemStructure.unapply明确指的是自动生成的unapplyNewName.unapply明确指的是你的。

答案 1 :(得分:2)

使用Any作为结果类型编译器无法确定取消应用函数的位置。您的unappl y仅定义String类型的行为。

这会有效:

val func: PartialFunction[String, Unit] = {
  case ItemStructure(item) =>
} 

否则尝试定义采用Any类型的unapply函数。