我尝试使用类型化参数在自定义类上进行模式匹配:
class Foo[A]
def isMyFoo[A: ClassTag](v: Any) = v match {
case mine: Foo[A] => "my foo"
case other: Foo[_] => "not my foo"
case _ => "not a foo"
}
这不起作用;无论Foo
的类型如何,我都会得到"my foo"
。
我能够做出像这样的工作的唯一方法是:
class Foo[A](implicit t: ClassTag[A]) {
val tag = t
}
def isMyFoo[A: ClassTag](v: Any) = v match {
case foo: Foo[_] =>
if (foo.tag == classTag[A]) "my foo"
else "not my foo"
case _ => "not a foo"
}
有更优雅的方式吗?我是否必须将ClassTag
保留在Foo
内?
答案 0 :(得分:4)
我是否必须将ClassTag保留在Foo中?
是。 Foo
的类型参数在运行时被删除,所以你知道的是你有一个Foo[_]
。唯一的方法是使用ClassTag
或TypeTag
保存类型信息。如果您要使用此路线,我建议您使用TypeTag
,因为您可以使用更精致的类型。 ClassTag
仍然只能模数类型擦除。
例如,使用ClassTag
,这是错误的:
scala> val fooListString = new Foo[List[String]]
fooListString: Foo[List[String]] = Foo@f202d6d
scala> isMyFoo[List[Int]](fooListString)
res4: String = my foo
但以下方法可行:
class Foo[A](implicit t: TypeTag[A]) {
val tag = t
}
def isMyFoo[A: TypeTag](v: Any) = v match {
case foo: Foo[_] =>
if (foo.tag.tpe =:= typeOf[A]) "my foo"
else "not my foo"
case _ => "not a foo"
}
scala> val fooListString = new Foo[List[String]]
fooListString: Foo[List[String]] = Foo@6af310c7
scala> isMyFoo[List[Int]](fooListString)
res5: String = not my foo