Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: set a field value reflectively from field name

I'm learning scala and can't find out how to do this:

I'm doing a mapper between scala objects and google appengine entities, so if i have a class like this:

class Student {
    var id:Long
    var name:String
}

I need to create an instance of that class, in java i would get the Field by it's name and then do field.set(object, value) but I can't find how to do so in scala.

I can't use java reflection since the fields of Student are seen as private and field.set throws an error because of that.

Thanks

like image 313
Damian Avatar asked Oct 19 '09 16:10

Damian


People also ask

How do you set a field value?

SetFieldValue(value = 10000.0); The FieldByName method returns the field object that represents the given field (salary_fld, in this example), and the SetFieldValue methods uses that field object to set the value of the field. If this method is successful, it returns ER_OK.

How to use reflection in Scala?

Types obtained through reflection can be instantiated by invoking their constructor using an appropriate “invoker” mirror (mirrors are expanded upon below). Let's walk through an example using the REPL: scala> case class Person(name: String) defined class Person scala> val m = ru. runtimeMirror(getClass.


1 Answers

Scala turns "var" into a private field, one getter and one setter. So in order to get/set a var by identifying it using a String, you need to use Java reflection to find the getter/setter methods. Below is a code snippet that does that. Please note this code runs under Scala 2.8.0 and handlings of duplicated method names and errors are nonexistent.

class Student {
  var id: Long = _
  var name: String = _
}

implicit def reflector(ref: AnyRef) = new {
  def getV(name: String): Any = ref.getClass.getMethods.find(_.getName == name).get.invoke(ref)
  def setV(name: String, value: Any): Unit = ref.getClass.getMethods.find(_.getName == name + "_$eq").get.invoke(ref, value.asInstanceOf[AnyRef])
}

val s = new Student
s.setV("name", "Walter")
println(s.getV("name"))  // prints "Walter"
s.setV("id", 1234)
println(s.getV("id"))    // prints "1234"
like image 147
Walter Chang Avatar answered Oct 19 '22 02:10

Walter Chang