1

I have the following code:

trait Vehicle{
   val speed:Int
}

case class Car(speed: Int, color: String) extends Vehicle
case class Plane(speed: Int, numberOfEngines: Int) extends Vehicle

case class Storage(vehicle: Vehicle, size:Int)

When using a trait as one of the named parameters of a case class, I loose the benefits of a case class, for example the copy method.

So if I want to update a vehicle speed like this:

val x = Storage(Car(100, "red"), 10)
x.copy(vehicle = x.vehicle.copy(speed = 30)) //this will not work.

This is obvious. The thing is it looks like the design here is bad, and that's why I ended with this problem.

Is there a better way to model this?

Tomer
  • 2,398
  • 1
  • 23
  • 31

1 Answers1

1

The copy() method is defined for a case class and not for a trait. Since a trait can also be implemented by a plain class, there is no guaranty that all implementation of trait Vehicle will have a copy method.

You now have two options

  • add a method withUpdatedSpeed(speed): Vehicle to Vehicle trait, so each subClass will provide a implementation

  • or case match on x.vehicle and manually construct vehicle Instances.

  • Those were my exact solutions for this. But it feels like I am doing it all wrong, and there must be a more elegant way to do it. any other options? – Tomer May 18 '17 at 08:20
  • 1
    Shapeless library does support this but I am not that familiar with it. You can follow this link http://www.cakesolutions.net/teamblogs/copying-sealed-trait-instances-a-journey-through-generic-programming-and-shapeless – Chetan Kumar Meena May 18 '17 at 17:29