Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overloading unapply method in case classes: scala

Tags:

scala

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"

like image 945
Ajay Avatar asked Oct 25 '11 05:10

Ajay


People also ask

What is Unapply method in Scala?

The unapply method breaks the arguments as specified and returns firstname object into an extractor . It returns a pair of strings if as an argument, the first name and last name is passed else returns none. Example : Scala.

Can case class have methods in Scala?

Case Classes You can construct them without using new. case classes automatically have equality and nice toString methods based on the constructor arguments. case classes can have methods just like normal classes.

Which is a method that is generated for us in a case class?

Case class constructor parameters are public val fields by default, so accessor methods are generated for each parameter. An apply method is created in the companion object of the class, so you don't need to use the new keyword to create a new instance of the class.

What is use of case class in Scala?

The one of the topmost benefit of Case Class is that Scala Compiler affix a method with the name of the class having identical number of parameters as defined in the class definition, because of that you can create objects of the Case Class even in the absence of the keyword new.


2 Answers

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.

like image 71
Didier Dupont Avatar answered Sep 18 '22 18:09

Didier Dupont


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.

like image 21
Francis Judge Avatar answered Sep 16 '22 18:09

Francis Judge