我尝试在Scala中进行集合匹配,而不使用scala.reflect.ClassTag
case class Foo(name: String)
case class Bar(id: Int)
case class Items(items: Vector[AnyRef])
val foo = Vector(Foo("a"), Foo("b"), Foo("c"))
val bar = Vector(Bar(1), Bar(2), Bar(3))
val fc = Items(foo)
val bc = Items(bar)
我们不能这样做:
fc match {
case Items(x) if x.isInstanceOf[Vector[Foo]]
}
因为:
警告:scala.collection.immutable.Vector [Foo](Vector [Foo]的基础)类型中的非变量类型实参Foo未被选中,因为已通过擦除将其消除了
这:
fc match {
case Items(x: Vector[Foo]) =>
}
但是我们可以这样做:
fc match {
case Items(x@(_: Foo) +: _) => ...
case Items(x@(_: Bar) +: _) => ...
}
bc match {
case Items(x@(_: Foo) +: _) => ...
case Items(x@(_: Bar) +: _) => ...
}
如您所见,我们正在检查-是集合Foo + vector还是Bar + vector。
这是我们遇到的一些问题:
还有一些更漂亮的方法吗? 像这样:
fc match {
case Items(x: Vector[Foo]) => // result is type of Vector[Foo] already
}
答案 0 :(得分:4)
您在这里所做的基本上是种令人不快的事情,因此我不确定是否可以以优美的方式做到这一点是一件好事,但就Shapeless而言,这是值得的TypeCase
更好一点:
case class Foo(name: String)
case class Bar(id: Int)
case class Items(items: Vector[AnyRef])
val foo = Vector(Foo("a"), Foo("b"), Foo("c"))
val bar = Vector(Bar(1), Bar(2), Bar(3))
val fc = Items(foo)
val bc = Items(bar)
val FooVector = shapeless.TypeCase[Vector[Foo]]
val BarVector = shapeless.TypeCase[Vector[Bar]]
然后:
scala> fc match {
| case Items(FooVector(items)) => items
| case _ => Vector.empty
| }
res0: Vector[Foo] = Vector(Foo(a), Foo(b), Foo(c))
scala> bc match {
| case Items(FooVector(items)) => items
| case _ => Vector.empty
| }
res1: Vector[Foo] = Vector()
请注意,尽管ClassTag
实例也可以通过这种方式使用,但它们并不能满足您的要求:
scala> val FooVector = implicitly[scala.reflect.ClassTag[Vector[Foo]]]
FooVector: scala.reflect.ClassTag[Vector[Foo]] = scala.collection.immutable.Vector
scala> fc match {
| case Items(FooVector(items)) => items
| case _ => Vector.empty
| }
res2: Vector[Foo] = Vector(Foo(a), Foo(b), Foo(c))
scala> bc match {
| case Items(FooVector(items)) => items
| case _ => Vector.empty
| }
res3: Vector[Foo] = Vector(Bar(1), Bar(2), Bar(3))
…如果您尝试使用ClassCastException
,则当然会抛出res3
。
这确实不是一件好事-在运行时检查类型会破坏参数性,使您的代码不那么健壮,等等。类型擦除是一件好事,而JVM上类型擦除的唯一问题是还不完整。
答案 1 :(得分:-2)
如果您需要使用隐式转换的简单操作。然后试试这个!
implicit def VectorConversionI(items: Items): Vector[AnyRef] = items match { case x@Items(v) => v }
Example:
val fcVertor: Vector[AnyRef] = fc // Vector(Foo(a), Foo(b), Foo(c))
val bcVertor: Vector[AnyRef] = bc // Vector(Bar(1), Bar(2), Bar(3))