Edward Peters
Edward Peters

Reputation: 4062

Scala: Case classes with shared parameter?

I don't know if there's a way to do this, but I want to be able to specify that a set of case classes all share a parameter (so I can access it without pattern matching).

EDIT: After some help I have

abstract class Test(val termName : String)
case class TestOne(value : Int, name : String = null) extends Test(name)
case class TesTwo(otherValue : Boolean, name : String = null) extends Test(name)

Which is almost exactly what I want, though it would be nice to get rid of the ugliness of having both name and termName.

Upvotes: 0

Views: 425

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170723

though it would be nice to get rid of the ugliness of having both name and termName.

Just make it a normal member of the supertype (which can easily be a trait), not a constructor parameter:

trait Test { 
  val name : String 
}
case class TestOne(value : Int, name : String = null) extends Test
case class TestTwo(otherValue : Boolean, name : String = null) extends Test

(The standard Scala style is name: String, no space before :.)

Upvotes: 3

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

If every implementation should have a separate, distinct implementation, declare abstract member and implement it in children:

abstract trait NamedCaseClass {
  def name: String
}
case class OneCase(number : Int) extends NamedCaseClass {
  override def name: String = "OneCase"
}
case class OtherCase(truth : Boolean) extends NamedCaseClass {
  override def name: String = "OtherCase"
}

If all implementations could just use some value that you can calculate on creation, you can use abstract class constructor:

abstract class NamedCaseClass(val name: String)
case class OneCase(number : Int) extends NamedCaseClass("OneCase")
case class OtherCase(truth : Boolean) extends NamedCaseClass("OtherCase")

If you have a sealed hierarchy you could also define it like this:

sealed trait NamedCaseClass {
  def nameOpt: Option[String] = this match {
    case OneCase(number) => Some(name.toString)
    case OtherCase(_)    => None
  }
}
case class OneCase(number : Int) extends NamedCaseClass
case class OtherCase(truth : Boolean) extends NamedCaseClass

Which one is more convenient pretty much depend on if you have a sealed hierarchy or open, if you can calculate value on creation or is this something more complicated that would work better as a method.

Upvotes: 3

Related Questions