I could not find a natural way to do something like that in scala :
class Car {
var speed: Int
var color: String
}
var myCar = new Car()
myCar.set {
speed = 5
color = "green"
}
I know it is possible in other languages as Groovy. I also know I can do it with a constructor like this :
val myCar = new Car {
speed = 5
color = "green"
}
I am interested in a way to do the same, not at the object construction but later, once the object has already been created
This is what I have been doing so far :
class Car (var speed: Int, var color: String) {
def set(f: (Car) => Unit) = {
f(this)
}
}
val myCar = new Car(5, "red")
myCar.set { c =>
c.speed = 12
c.color = "green"
}
But I do not like the need to write the 'c' var for every attribute
Any idea on how I can do it or if there is an easier way ??
You should avoid mutable classes unless absolutely necessary. You would do normally this in Scala:
case class Car(speed: Int, color: String)
val c1 = Car(5, "red")
val c2 = c1.copy(speed = 12, color = "green")
(Then c2
is a new version of the car, while c1
remains unchanged.)
If you want to stick with your mutable type, why not just
class Car(var speed: Int, var color: String)
val myCar = new Car(5, "red")
import myCar._
speed = 12
color = "green"
Going with a dedicated set
method:
class Car(var speed: Int, var color: String) {
def set(speed: Int = this.speed, color: String = this.color): Unit = {
this.speed = speed
this.color = color
}
}
val myCar = new Car(5, "red")
myCar.set(speed = 12, color = "green")
myCar.set(color = "blue")
Although we all agree to say var reassignement is ugly, this is a possible solution
object DoTo {
def apply[T](that: T)(functions: (T) => Unit*): T = {
functions foreach { _.apply(that) }
that
}
}
class Car (var speed: Int, var color: String) {
def move() = println("moving")
def stop() = println("stop")
}
val myNewCar = DoTo(new Car(12, "red")) (
_.move(),
_.stop(),
_.speed = 15,
_.color = "green"
)
This is not exactly what I wanted initially but I cannot find anything simpler whithout using macros :-(
You can do it by importing a variable:
class Car {
var speed: Int = _
var color: String = _
}
// ...
val myCar = new Car();
// a blocks that works with myCar:
{
import myCar._
// access the content without any prefix
speed = 5
color = "green"
}