获取class-attribute或class-function的名称作为String

时间:2010-06-10 18:39:50

标签: scala scala-2.8

说我有以下课程:

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

是否可以通过反射或其他方式以类型安全的方式获取“firstName”的String表示?或生成的“getFirstName”函数的字符串表示?

如果它会以某种方式显示会很好:

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

修改

好的,需要更多解释;)

假设我想构建一个这样的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 个答案:

答案 0 :(得分:2)

我假设您不知道要检查的类中的方法和属性名称(否则为什么要获取其名称而不是仅仅键入它们?)。此示例显示如何获取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...

答案 1 :(得分:2)

坏消息是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"!
    }
  } 
}
}

那有多酷?例如,如果您尝试将年龄与String进行比较,则无法编译。当然,如果你使用p.ssn或其他一些未知字段,也不会编译。