PHP introduces a method that allows you to pick out all public values of an instance. Scala有什么办法吗?这是为了获取实例化类(而不是对象)的所有公共字段的所有值。
让我们假设我有这个课程
class TestElement( datatype: Datatype, var subject: String, var day: Int, var time: Int )
extends DataElement( datatype: Datatype ) {
def to( group: Group ) = group.add( this );
}
var element = new TestElement( datatype, "subject", 1, 1 );
我所需要的方法是获取一个Map或两个值的集合。
var element.method // the function I need
ret: ( ("subject", "subject"), ("day", 1), ("time", 1) ) // its output
答案 0 :(得分:21)
是时候睡觉了,所以我没时间找到完整的答案,但看看element.getClass.getFields
(或getDeclaredFields
私有字段的结果) - 你可以致电{{1}在getValue(element)
个对象上获取它们的值。
现在醒来,仍然没有更好的答案,所以:
首先,请注意,在Java术语中,您的类没有公共字段主题,它具有私有字段主题和访问者方法subject()和subject_ $ eq(String)。
您可以如上所述迭代私有字段对象,从对中填充地图:
Field
现在,您可以在TestElement上定义此方法(将def getFields(o: Any): Map[String, Any] = {
val fieldsAsPairs = for (field <- o.getClass.getDeclaredFields) yield {
field.setAccessible(true)
(field.getName, field.get(o))
}
Map(fieldsAsPairs :_*)
}
替换为o
),或者通常更有用地定义转换,以便您可以在任何引用上调用getFields
this
那样
implicit def any2FieldValues[A](o: A) = new AnyRef {
def fieldValues = getFields(o)
}
会给出你想要的结果。
答案 1 :(得分:3)
根据Philippe的回答,你可以为案例分类做到这一点。
更广泛地说,同样的技术适用于 Product
的任何子类。除了案例类之外,元组是另一个明显的例子,但列表远不止于此。
在这里查看“已知的子类”:http://www.scala-lang.org/api/current/scala/Product.html
答案 2 :(得分:2)
对于案例类,你可以做一些比较接近的事情:
case class SomeEntity(name : String, value : Int, misc : Boolean)
val s = SomeEntity("Tom", 42, false)
println(s.productIterator.map(_.toString).mkString(", ")) // "Tom, 42, false"
...正如您所料,productIterator迭代Any类型的元素。此方法仅针对案例类自动生成,您不会检索该字段的名称。对于更多的东西,你需要使用反射,为此,你可能想要等待2.10出来。
答案 3 :(得分:1)
对于那些试图通过使@duncan的方法更强大来改善这一点的人来说,请注意:
您可以执行以下操作,而不是返回Map[String, Any]
,其中值的类型为Any,您可以执行以下操作:
def propertiesAsPairs() = {
val fields = (this.getClass.getDeclaredFields())
for ( field <- fields ) yield {
field.setAccessible( true );
( field.getName, field.get( this ) );
}
}
答案 4 :(得分:0)
Scala故意让val
,var
和def
共享一个公共接口,因此您可以使用后者替换前两个而不会破坏任何代码 - 甚至不需要重新编译。
所以,尽管可以做你想做的事情,但它会导致代码变得脆弱,这就是它不应该做的事情。