我想实现以下详尽的匹配,但我无法弄清楚是否删除了类型参数,因此警告它被删除:
sealed trait Q[+V]
case object QEmpty extends Q[Nothing]
sealed trait QNonEmpty[V] extends Q[V] {
def foo: V
}
final class QLeaf[V](val foo: V) extends QNonEmpty[V]
final class QNode[V](val foo: V, var children: Array[Q[V]]) extends QNonEmpty[V]
def test[V](n: Q[V]): String = n match {
case QEmpty => "empty"
case n: QNonEmpty[V] => n.foo.toString // warning: type parameter V is erased
}
在我的具体案例中,case n
匹配的正文非常大,我不想添加更多匹配子句,以便我匹配QLeaf
和QNode
(因为在我的具体情况中,有两个以上的子类,它们也是可变的,因此不应该是case类)。已解决的类型必须为QNonEmpty[V]
,不能为QNonEmpty[_]
。
我可以为QNonEmpty
创建一个与QLeaf
和QNode
匹配的提取器吗?
答案 0 :(得分:3)
您可以使用存在类型匹配具有已删除参数的类型:
type AnyNonEmpty = QNonEmpty[X] forSome { type X }
in match {
case x: AnyNonEmpty => //...
}
提取器可能如下所示:
object QNonEmpty {
def unapply(in: QNonEmpty[_]): Option[Any] = Some(in.foo)
}
def test[ V ]( n: Q[ V ]) : String = n match {
case QEmpty => "empty"
case QNonEmpty(foo) => foo.toString
}
我认为您不能编写类型安全提取器,因为在示例代码中,方法的类型参数也会被删除。
也许您应该考虑在您的特征中添加fold
方法并重写您的示例:
sealed trait Q[ +V ] {
def fold[A](e: => A, f: V => A): A = e
}
case object QEmpty extends Q[ Nothing ]
sealed trait QNonEmpty[ V ] extends Q[ V ] {
def foo: V
override def fold[A](e: => A, f: V => A) = f(foo)
}
// ...
def test[V](n: Q[V]) = n.fold("empty", _.toString)