在 Scala/Java 中获取实例的公共字段(及其各自的值)
php介绍了一种允许您挑选实例所有公共价值的方法。 有什么办法在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 );
从所讨论的方法中需要的东西是获得一两个值的地图。
var element.method // the function I need
ret: ( ("subject", "subject"), ("day", 1), ("time", 1) ) // its output
PHP introduces a method that allows you to pick out all public values of an instance. Is there any way to do this in Scala? That is to fetch all values of all public fields of an instantiated class (not object).
Let's us assume I have this class
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 );
What I need from the method in question, is to get a Map or two Collections of values.
var element.method // the function I need
ret: ( ("subject", "subject"), ("day", 1), ("time", 1) ) // its output
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
该睡觉了,所以我没有时间给出完整的答案,但看看
element.getClass.getFields
(或getDeclaredFields
对于私有字段)的结果 -您可以在Field
对象上调用getValue(element)
来获取它们的值。现在清醒了,仍然没有更好的答案,所以:
首先,请注意,用 Java 术语来说,您的类没有公共字段主题,它拥有的是私有字段主题和访问器方法 subject() 和 subject_$eq(String )。
您可以如上所述迭代私有字段对象,从对中填充 Map:
现在您可以在 TestElement 上定义此方法(将
o
替换为this
),或者更普遍的是,定义一个转换,以便您可以在任何引用上调用 getFields,这样
就会得到您想要的结果。
It's time for bed, so I don't have time for a full answer, but look at the results of
element.getClass.getFields
(orgetDeclaredFields
for private fields) - you can callgetValue(element)
on theField
objects to fetch their values.Awake now, and still no better answer, so:
First, note that in Java terms, your class doesn't have a public field subject, what it has is a private field subject and accessor methods subject() and subject_$eq(String).
You can iterate over the private field objects as described above, populating a Map from the pairs:
Now you can either define this method on TestElement (replacing
o
withthis
), or more generally usefully define a conversion so that you can call getFields on any referenceSo that
will give the result you want.
根据菲利普的回答,您可以对案例类执行此操作。
但更广泛地说,相同的技术适用于
Product
的任何子类。除了案例类之外,元组是另一个明显的例子,但列表远不止于此。在这里查看“已知子类”: http://www .scala-lang.org/api/current/scala/Product.html
A per Philippe's answer, you can do this for case classes.
More broadly though, the same technique works for any subclass of
Product
. As well as case classes, Tuples are another obvious example, but the list is far more extensive than that.Take a look at the "known subclasses", here: http://www.scala-lang.org/api/current/scala/Product.html
对于案例类,您可以做一些与此相对接近的事情:
...正如您所期望的,productIterator 迭代 Any 类型的元素。此方法仅针对案例类自动生成,您将不会检索字段的名称。对于更多的事情,您将需要使用反射,为此,您可能需要等待 2.10 的发布。
You can do something relatively close to this for case classes:
...as you would expect, productIterator iterates over elements of type Any. This method is automatically generated for case classes only, and you will not retrieve the name of the field. For anything more, you will need to use reflection, and for that, you may want to wait for 2.10 to come out.
只是给那些试图通过制作@Duncan的方法类型的人的注释:
而不是返回
map [string,任何]
,其中值是键入的,您可以执行下列的:Just a note to those who try to improve this by making @duncan 's approach type-stronger:
Instead of returning a
Map[String, Any]
, where the value is typed as Any, you could do following:Scala故意制作
val
,var
和def
共享一个共同的接口,因此您可以用后者替换前两个而不会破坏任何代码 - 甚至不需要重新编译。因此,虽然可以做您想做的事情,但它会导致脆弱的代码,而这种代码不应该做。
Scala deliberately makes
val
,var
anddef
share a common interface, so you can replace the former two with the latter without breaking any code -- without even requiring a recompile.So, while it is possible to do what you want, it would result in brittle code, that does the sort of thing it shouldn't do.