在case类中重载unapply方法:scala

时间:2011-10-25 05:45:09

标签: scala

考虑以下代码:

case class User(id: Int, name: String)
object User{
  def unapply(str: String) = Some(User(0, str))
}

Scala抱怨“错误:无法解析重载的unapply;案例类User(id:Int,str:String)” 是不是可能超载不应用?

更新:     不适用较大的元组大小。

case class User(id: Int, str: String)
object User{
  def unapply(s: String) = Some((User(0, s), s, 1234))
}

编译器仍然抱怨“无法解决重载unapply”

2 个答案:

答案 0 :(得分:8)

您的unapply方法无法用于模式匹配

适用于

def unapply(arg: <type to match>) : Option[(<matched fields types>)]

(如果只有一个字段,则没有元组,如果没有字段,则为布尔而不是选项。)

用户的标准不适用是(The Scala Language Specification p.67)

def unapply(u: User) = 
  if (u eq null) None 
  else Some((u.id, u.name))

您想要的是匹配具有零ID的用户,如

user match {case User(name) => ....}

那将是

def unapply(u: User): Option[String] = 
  if(u eq null || u.id != 0) None 
  else Some(u.name)

如果你想要一个字符串可以作为用户匹配(这将是相当奇怪的)

def unapply(s: String): Option[User] = Some(User(0, s))

可以使用

"john" match case User(u) => ... // u is User(0, john)

我想你想要前者。在这种情况下,您的apply和标准的两个方法都具有相同的参数列表(一个User参数),因此它们不兼容。这可能被视为有点不幸,因为当方法被称为提取器时,区分元素实际上是结果元组的大小,而不是参数的类型。

但是,您的方法虽然无法作为提取器生效,但不会导致冲突。我在规范中找不到禁止它的东西。尽管如此,它仍然是无用的,并且正确的方法是不允许的。

答案 1 :(得分:2)

您无法覆盖unapply(特别是)的原因很可能是它与case类的companiation对象自动创建的签名相同。记住函数的签名没有考虑其覆盖的用途的返回值。