jeypijeypi
jeypijeypi

Reputation: 373

Case Classes with optional fields in Scala

For example, I have this case class:

case class Student (firstName : String, lastName : String)

If I use this case class, is it possible that supplying data to the fields inside the case class are optional? For example, I'll do this:

val student = new Student(firstName = "Foo")

Thanks!

Upvotes: 30

Views: 42159

Answers (3)

akauppi
akauppi

Reputation: 18066

I would see two ways this is normally done.

1. default parameters

case class Student (firstName : String, lastName : String = "")

Student("jeypijeypi")   # Student(jeypijeypi,)

2. alternative constructors

case class Student (firstName : String, lastName : String)

object Student {
    def apply(firstName: String) = new Student(firstName,"")
}

Student("jeypijeypi")   # Student(jeypijeypi,)

Which one is better depends slightly on the circumstances. The latter gives you more freedom: you can make any parameter(s) optional, or even change their order (not recommended). Default parameters need always to be at the end of the parameter list, I think. You can also combine these two ways.

Note: within the alternative constructors you need new to point the compiler to the actual constructor. Normally new is not used with case classes.

Upvotes: 11

tgr
tgr

Reputation: 3608

If you just want to miss the second parameter without a default information, I suggest you to use an Option.

case class Student(firstName: String, lastName: Option[String] = None)

Now you might create instances this way:

Student("Foo")
Student("Foo", None)            // equal to the one above
Student("Foo", Some("Bar"))     // neccesary to add a lastName

To make it usable as you wanted it, I will add an implicit:

object Student {
  implicit def string2Option(s: String) = Some(s)
}

Now you are able to call it those ways:

import Student._

Student("Foo")
Student("Foo", None)
Student("Foo", Some("Bar"))
Student("Foo", "Bar")

Upvotes: 37

om-nom-nom
om-nom-nom

Reputation: 62855

You were close:

case class Student (firstName : String = "John", lastName : String = "Doe")

val student = Student(firstName = "Foo")

Another possibility is partially applied function:

case class Student (firstName : String, lastName : String)

val someJohn = Student("John", _: String)
//someJohn: String => Student = <function1>

val johnDoe = someJohn("Doe")
//johnDoe: Student = Student(John,Doe)

And to be complete, you can create some default object and then change some field:

val johnDeere = johnDoe.copy(lastName="Deere")
//johnDeer: Student = Student(John,Deere)

Upvotes: 36

Related Questions