如何读取扩展 Any 但不扩展 AnyRef 的 Scala 对象的类?
我有一个如下所示的异构列表:
val l = List(1, "One", true)
并且我需要通过仅提取属于给定类的对象来过滤其对象。为此,我编写了一个非常简单的方法,如下所示:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (_.asInstanceOf[AnyRef].getClass() == c)
请注意,我有义务向 AnyRef 添加显式转换,以避免此编译问题:
error: type mismatch;
found : _$1 where type _$1
required: ?{val getClass(): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
are possible conversion functions from _$1 to ?{val getClass(): ?}
l filter (_.getClass() == c)
但是,通过这种方式,调用:
filterByClass(l, classOf[String])
按预期返回:
List(One)
但当然同样不会例如,对于 Int 不起作用,因为它们扩展了 Any 但不是 AnyRef,因此通过调用:
filterByClass(l, classOf[Int])
结果只是空 List。
有没有办法让我的 filterByClass 方法甚至可以与 Int、Boolean 和扩展 Any 的所有其他类一起使用?
I have an heterogeneous List like the following one:
val l = List(1, "One", true)
and I need to filter its objects by extracting only the ones belonging to a given Class. For this purpose I wrote a very simple method like this:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (_.asInstanceOf[AnyRef].getClass() == c)
Note that I am obliged to add the explicit conversion to AnyRef in order to avoid this compilation problem:
error: type mismatch;
found : _$1 where type _$1
required: ?{val getClass(): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
are possible conversion functions from _$1 to ?{val getClass(): ?}
l filter (_.getClass() == c)
However in this way the invocation of:
filterByClass(l, classOf[String])
returns as expected:
List(One)
but of course the same doesn't work, for example, with Int since they extends Any but not AnyRef, so by invoking:
filterByClass(l, classOf[Int])
the result is just the empty List.
Is there a way to make my filterByClass method working even with Int, Boolean and all the other classes extending Any?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
collect
方法已经完成了您想要的操作。例如,要收集集合中的所有 Int,您可以编写这当然仅在您对类型进行硬编码时才有效,但由于基元的处理方式与引用类型不同,因此实际上最好这样做。您可以使用某些类型类让您的生活更轻松:
然后您甚至可以在不传递
Class[A]
实例的情况下使用它:The
collect
method already does what you want. For example to collect allInt
s in a collection you could writeThis of course only works when you hardcode the type but as primitives are handled differently from reference types it is actually better to do so. You can make your life easier with some type classes:
Then you can use it without even passing a
Class[A]
instance:使用 isInstanceOf:
编辑:
根据OP的要求,这是另一个将检查移入方法的版本。我找不到使用 isInstanceOf 的方法,因此我更改了实现以使用 ClassManifest:
一些使用场景:
如上所示,此解决方案不适用于 Scala 的 Int 类型。
Using isInstanceOf:
edit:
As the OP requested, here's another version that moves the check in a method. I Couldn't find a way to use isInstanceOf and so I changed the implementation to use a ClassManifest:
Some usage scenarios:
As can be seen above, this solution doesn't work with Scala's Int type.
List[Any] 中元素的类永远不是 classOf[Int],因此其行为符合预期。你的假设显然让这出乎意料,但很难给你更好的方法,因为正确的方法是“不要这样做”。
您认为关于异构列表的成员的类别可以说些什么?也许这很说明问题。我很好奇你认为 java 是如何做得更好的。
The class of an element in a List[Any] is never classOf[Int], so this is behaving as expected. Your assumptions apparently leave this unexpected, but it's hard to give you a better way because the right way is "don't do that."
What do you think can be said about the classes of the members of a heterogenous list? Maybe this is illustrative. I'm curious how you think java does it better.
这对我有用。这是你想要的吗?
This worked for me. Is this what you want?
尽管我的解决方案可能不如 这个我发现我的更快更容易。我刚刚定义了一个这样的方法:
因此,通过在我以前的 filterByClass 方法中使用它,如下所示:
的调用:
返回。
只是按预期
Despite my solution could be less elegant than this one I find mine quicker and easier. I just defined a method like this:
So by using it in my former filterByClass method as it follows:
the invocation of:
just returns
as expected.
最后,这个问题简化为找到基元和相应的装箱类型之间的映射。
也许可以从
scala.reflect.Inspiration
(未包含在 2.8.0 的最终版本中)获得帮助,特别是getAnyValClass
函数(此处稍作编辑)过滤器的功能很简单
,调用如下:
At the end, this problem reduces to find a map between a primitive and the corresponding boxed type.
Maybe a help can arrive from
scala.reflect.Invocation
(not included in the final version of 2.8.0), thegetAnyValClass
function in particular (here slightly edited)With this function the filter is as easy as
and the invocation is: