1

I had a case class with a option parameter, let's say:

case class Student(id: Option[Int], name: String)

To get a Student instance, not only I could use Student(Some(1), "anderson"), I also want this form to be a valid way Student(2,"Sarah")

I guess I have to create a Int => Option[Int] and put it somewhere. So what's the best way to do so?

Update

As mentioned in the comment, override apply method will block calling it by Student.apply _

noru
  • 526
  • 3
  • 15

2 Answers2

9

It might be easier to just make an apply method in a companion object.

case class Student(id: Option[Int], name: String)

object Student {
  def apply(id: Int, name: String): Student = {
    Student(Some(id), name)
  }
}
mattinbits
  • 10,370
  • 1
  • 26
  • 35
Brian Kent
  • 3,754
  • 1
  • 26
  • 31
  • 2
    I would strongly suggest naming this method something other than `apply`. – Travis Brown Aug 27 '15 at 17:25
  • 1
    @TravisBrown Why? Isn't the point of this to be able to use it the same as the auto-generated `apply` method? Unless it's named `apply`, he can't use `Student(2, "Sarah")`. – resueman Aug 27 '15 at 17:45
  • 1
    @resueman There are [lots of reasons to avoid overloading](http://stackoverflow.com/a/2512001/334519). One additional one off the top of my head for this case specifically: it would break Play's automatic JSON codec generation (and presumably similar mechanisms in other projects). – Travis Brown Aug 27 '15 at 18:00
  • 1
    Thanks @Brian, it is a convenient way indeed! And thanks to Travis for further information! – noru Aug 28 '15 at 03:19
  • I totally agree with @TravisBrown when he says: "it would break Play's automatic JSON codec generation (and presumably similar mechanisms in other projects)". I can hear you there and, in that case, you don't get the clearest error message ever, to use an understatement. – lambdista Aug 28 '15 at 14:00
1

An alternative solution using implicit conversions:

implicit def intToOption(x: Int) = Some(x)
case class Student(id: Option[Int], name: String)

scala> Student(1,"Nu")
res1: Student = Student(Some(1),Nu)
marios
  • 8,874
  • 3
  • 38
  • 62
  • I am aware of this approach. But it requires bringing the implicit conversion in to the scope where you try to construct the case class this way, which can be very tedious. Is there a technic to cut the "import" effort? – noru Aug 28 '15 at 07:59
  • 1
    Please don't do this—implicit conversions are almost always a terrible idea, and the terribleness is proportional to how often you use values of the types involved, so an implicit conversion from `Int` to anything is just bad news. – Travis Brown Aug 28 '15 at 14:48
  • Still deciding on implicit myself. As always, power comes with responsibility. If you are doing this for production level code, you might have to go with some more "safe" solution. If you are doing this for your own project, then I feel it's cool enough to deserve a chance. – marios Aug 28 '15 at 23:45