Получить имя класса-атрибута или функции-класса в виде строки - PullRequest
3 голосов
/ 10 июня 2010

Скажите, что у меня есть следующий класс:

class Person {
  @BeanProperty
  var firstName: String = _
}

Возможно ли получить строковое представление "firstName" безопасным для типа способом, отражением или чем-то еще?Или строковое представление сгенерированной функции getFirstName?

Было бы хорошо, если бы она выглядела так:

val p = new Person
p.getFunction(p.getFirstName).toString // "getFirstName"
p.getAttribute(p.firstName).toString   // "firstName"

EDIT

Хорошо, нужны дополнительные пояснения;)

Скажем, я хочу построить запрос SQL следующим образом:

val jpql = "select p from Person p where p.age > 20";

Итак, я хочу сделать его максимально безопасным и написать что-то вродеэто:

val jpql = "select p from " + classOf[Person].getName + " where p." + 
  Person.getAttName(p.age) + " > 20";

Таким образом, если в будущем можно будет реорганизовать код Scala, я мог бы изменить имя атрибута Person, не нарушая мой код.

Ответы [ 2 ]

2 голосов
/ 11 июня 2010

Плохая новость в том, что у Scala нет возможности ссылаться на таких участников.Вы можете получить «ссылку на метод», подобную этой:

scala> class Person(val firstName:String)         
defined class Person

scala> val methodRef = new Person("i").firstName _
methodRef: () => String = <function0>

scala> methodRef()                                
res1: String = i

Но она не дает вам того, что вам нужно.Хорошей новостью является то, что есть несколько библиотек, которые предоставляют вам этот тип JDBC с безопасным типом.Вот ваш код, используя Squeryl :

import org.squeryl.Schema
import org.squeryl.Session
import org.squeryl.PrimitiveTypeMode._
import org.squeryl.adapters.H2Adapter
import org.squeryl.SessionFactory

object Sample {
case class Person(val firstName:String, val age:Int)

object AppSchema extends Schema {
  val people = table[Person]("People")
}

def main(args:Array[String]) { 
  import AppSchema.people
  Class.forName("org.h2.Driver")
  SessionFactory.concreteFactory = Some(()=> Session.create(java.sql.DriverManager.getConnection("jdbc:h2:~/temp/db", "sa", ""), new H2Adapter))

  transaction {
    AppSchema.create
    people.insert(new Person("ifischer", 92)) 
    people.insert(new Person("baby", 2)) 
    for (olderPerson <- from(people)(p=> where(p.age gt 20) select(p))) {
      println(olderPerson) //wont return "baby"!
    }
  } 
}
}

Насколько это круто?Это не скомпилируется, если, например, вы попытаетесь сравнить возраст со строкой.Конечно, он также не скомпилируется, если вы используете p.ssn или другое неизвестное поле.

2 голосов
/ 10 июня 2010

Я предполагаю, что вы не знаете имен методов и атрибутов в классе, который вы хотите проверить (в противном случае, почему вы хотите получить их имена, а не просто вводить их?).В этом примере показано, как получить имена всех методов класса java.lang.String.

scala> classOf[String].getMethods.map(_.getName)
res4: Array[java.lang.String] = Array(equals, hashCode, toString, charAt, compareTo, 
compareToIgnoreCase, concat, endsWith, equalsIgnoreCase, getBytes, getBytes, getBytes, 
getChars, indexOf, indexOf, indexOf, indexOf, intern, lastIndexOf, lastIndexOf, 
lastIndexOf, lastIndexOf, length, regionMatches, regionMatches, replace, startsWith, 
startsWith, substring, substring, toCharArray, toL...
...