overloading unapply method in case classes: scala

2020-06-17 07:21发布

问题:

Consider the following piece of code:

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

Scala complains "error: cannot resolve overloaded unapply; case class User(id: Int, str: String)" Is it not possible to overload unapply?

update: unapply with larger tuple size.

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

compiler still complains "cannot resolve overloaded unapply"

回答1:

Your unapply method could not be used in pattern matching

It works with

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

(no tuple if only one field, boolean instead than Option if no field).

The standard unapply of User would be (The Scala Language Specification p. 67)

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

It what you want is to match a user with a zero id as in

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

that would be

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

If you want that a string can match as a User (this would be rather bizarre)

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

It would work with

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

I guess you want the former one. In which case both your apply and the standard one are two methods with the same argument list (one User parameter), so they are not compatible. This may be seen as a little unfortunate, as when methods are called as extractors, the distinguishing element is actually the size of the result tuple, not the type of the arguments.

Your method however, while not valid as an extractor, causes no conflict. I could not find something in the spec that would forbid it. Still, it is useless and a useful method would rightly not be allowed.



回答2:

The reason that you can't override the unapply (especially) is most probably that it has the same signiture as the one that is automatically created by a case class's compantion object. Remembering that a function's signiture does not take into account its return value for the piurpose of overriding.



标签: scala