1

I am trying to use Scala + Play 2.4.2 on a side project, I was writing a json parser and IntelliJ suggested this fix for my syntax.

I can't understand what this means

For me this (Person.apply, _) should be written (Person.apply _), but like that I get a cannot resolve symbol apply and the code does not compile.

Since I have an overloaded constructor shouldn't (Person.apply _) call it with the parameters from the valuereads function?

package models

import play.api.libs.json._
import play.api.libs.functional.syntax._

case class Person(id: Long = 0, name: String, age: Int){
  def this(name: String, age: Int) = this(0, name, age)
}

object Person {

  implicit val personFormat = Json.format[Person]

  implicit val valuereads = (__ \ "value").read {(
  (__ \ "name").read[String] and
  (__ \ "age").read[Int]
   )(Person.apply, _)   //**<=== THIS, what apply, _ stands for**

  def apply(name: String, age: Int) = new Person(name, age)
}

The fixed syntax still does not compile, but I get no warnings. What am I doing wrong here?

BTW I am following this info : https://www.playframework.com/documentation/2.4.x/ScalaJsonCombinators

Cristiano Fontes
  • 4,920
  • 6
  • 43
  • 76

1 Answers1

2

You're missing a few things here. For starters, while alternate constructors inside of a case class are permitted, it's often considered best practice to avoid overloading methods in Scala (see the discussion here Why "avoid method overloading"?). If you want to provide a "smart constructor", you can place one in the Person companion object, like so:

object Person {
  def makePerson(name: String, age: Int) = Person(name = name, age = age)
}

notice that I didn't use the new keyword which should only be used for plain old classes. You could also use apply in the companion object as you've done, but then there will be the ambiguity you've encountered here where the Reads instance isn't sure if you mean the companion object or the case class itself.

Also, note that your alternate constructor in the case class really does nothing more than what your default argument already accomplishes. If you simply place the param with the default argument in the last position, like this:

case class Person(name: String, age: Int, id: Long = 0)

then you can just do

Person("bob", 25) 

to construct a Person and 0 will be used for the id.

Community
  • 1
  • 1
LuxuryMode
  • 33,401
  • 34
  • 117
  • 188
  • 1
    Using `case class Person` gives you the companion object for free. If you define `object Person`, do you loose methods like `copy`, `apply` and therefore you need to redefine them (if needed) ... ? – ccheneson Aug 17 '15 at 14:52