2009-10-19 7 views
17

Я учусь Скал и не могу узнать, как это сделать:Scala: установить значение поля рефлекторно от имени поля

Я делаю картограф между объектами SCALA и Google AppEngine сущностей, так что если я есть класс, как это:

Мне нужно создать экземпляр этого класса, в Java я хотел бы получить поле по его имени, а затем сделать field.set(object, value), но я не могу найти, как сделать это в Скале.

Я не могу использовать java-отражение, так как поля Student видны как private, а field.set - это ошибка из-за этого.

Благодаря

ответ

36

Scala превращает «вар» в частное поле, один геттерные и один сеттер. Поэтому, чтобы получить/установить var, идентифицируя его с помощью String, вам нужно использовать отражение Java, чтобы найти методы getter/setter. Ниже приведен фрагмент кода, который делает это. Обратите внимание, что этот код работает под Scala 2.8.0, а экземпляры дублированных имен методов и ошибок несуществуют.

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" 
+0

Спасибо! это было очень полезно, я принял участие в вашем коде и отлично работал в Scala. 2.7.6 – Damian

+0

Вы также можете напрямую выбрать метод по имени, если вы используете getClass.getDeclaredMethod, если знаете заранее типы параметров метода! –

+0

Почему это лучше, чем установка поля.setAccessible (true)? – Yael