我尝试在不使用scala.reflect.classtag
的情况下在Scala中进行匹配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](向量[foo]的基础[foo])中的非变量类型参数foo 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) +: _) => ...
}
您可以看到,我们正在检查 - 是收集 vector或bar vector。
,我们有一些问题:
- 我们可以做矢量(foo(" 1"),bar(2)),这将与foo匹配。
- 我们仍然需要" val结果= x.asinstance [vector [bar]]" class cast for Result提取
有一些更美丽的方法吗?这样:
fc match {
case Items(x: Vector[Foo]) => // result is type of Vector[Foo] already
}
您在这里做的事情从根本上只是不愉快的,所以我不确定以美丽的方式做到这一点是一件好事,但是对于它的价值来说是一件好事,无形的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))
…如果您尝试使用res3
,这当然会扔ClassCastException
S。
如果您想要使用隐式转换简单的东西。然后尝试!
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))