Scala 案例类映射扩展
在 groovy 中可以这样做:
class Foo {
Integer a,b
}
Map map = [a:1,b:2]
def foo = new Foo(map) // map expanded, object created
我知道 Scala 不具有任何意义,Groovy,但我想知道是否支持这种情况下的地图扩展
简单地说,我尝试并失败了:
case class Foo(a:Int, b:Int)
val map = Map("a"-> 1, "b"-> 2)
Foo(map: _*) // no dice, always applied to first property
相关的 线程 显示了问题的可能解决方案。
现在,从我所了解到的情况来看,至少从 Scala 2.9.1 开始,关于案例类的反射基本上是无操作的。最终的结果似乎是人们被迫进行某种形式的手动对象创建,考虑到 Scala 的强大功能,这有点讽刺。
我应该提到该用例涉及 servlet 请求参数映射。具体来说,使用 Lift、Play、Spray、Scalatra 等,我想获取经过清理的参数映射(通过路由层过滤)并将其绑定到目标案例类实例,而不需要手动创建对象,也不需要指定其类型。这将需要“可靠”的反射和像“str2Date”这样的隐式来处理类型转换错误。
也许在 2.10 中有了新的反射库,实现上述内容将是小菜一碟。刚接触 Scala 2 个月,所以只是浅尝辄止;我现在没有看到任何直接的方法来实现这一点(对于经验丰富的 Scala 开发人员来说,也许是可行的)
In groovy one can do:
class Foo {
Integer a,b
}
Map map = [a:1,b:2]
def foo = new Foo(map) // map expanded, object created
I understand that Scala is not in any sense of the word, Groovy, but am wondering if map expansion in this context is supported
Simplistically, I tried and failed with:
case class Foo(a:Int, b:Int)
val map = Map("a"-> 1, "b"-> 2)
Foo(map: _*) // no dice, always applied to first property
A related thread that shows possible solutions to the problem.
Now, from what I've been able to dig up, as of Scala 2.9.1 at least, reflection in regard to case classes is basically a no-op. The net effect then appears to be that one is forced into some form of manual object creation, which, given the power of Scala, is somewhat ironic.
I should mention that the use case involves the servlet request parameters map. Specifically, using Lift, Play, Spray, Scalatra, etc., I would like to take the sanitized params map (filtered via routing layer) and bind it to a target case class instance without needing to manually create the object, nor specify its types. This would require "reliable" reflection and implicits like "str2Date" to handle type conversion errors.
Perhaps in 2.10 with the new reflection library, implementing the above will be cake. Only 2 months into Scala, so just scratching the surface; I do not see any straightforward way to pull this off right now (for seasoned Scala developers, maybe doable)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好消息是 Scala 的 Product 接口由所有案例类实现,实际上并没有让这件事变得非常困难。我是一个名为 Salat 的 Scala 序列化库的作者,该库提供了一些实用程序,用于使用 pickled Scala 签名来获取键入的字段信息
https ://github.com/novus/salat - 查看 salat-util 包中的一些实用程序。
事实上,我认为这是 Salat 应该做的事情——多好的主意啊。
回复:DC Sobral 关于在编译时验证参数的不可能的观点 - 点,但实际上这应该在运行时工作,就像反序列化任何其他没有结构保证的东西一样,比如 JSON 或 Mongo DBObject。此外,Salat 还具有利用提供的默认参数的实用程序。
Well, the good news is that Scala's Product interface, implemented by all case classes, actually doesn't make this very hard to do. I'm the author of a Scala serialization library called Salat that supplies some utilities for using pickled Scala signatures to get typed field information
https://github.com/novus/salat - check out some of the utilities in the salat-util package.
Actually, I think this is something that Salat should do - what a good idea.
Re: D.C. Sobral's point about the impossibility of verifying params at compile time - point taken, but in practice this should work at runtime just like deserializing anything else with no guarantees about structure, like JSON or a Mongo DBObject. Also, Salat has utilities to leverage default args where supplied.
这是不可能的,因为不可能在编译时验证所有参数是否都已在该映射中传递。
This is not possible, because it is impossible to verify at compile time that all parameters were passed in that map.