基类上的模式匹配和Scala中的所有派生类

时间:2012-02-25 10:22:43

标签: generics scala types pattern-matching

我正在努力实现这样的目标:

def a(b: Any) = {
  b match {
     case x: Seq[String] => println("x")
  }
}

// somewhere else

a(List("b"))

因此,我希望看到“x”被打印,而我却不会。

基本上我想匹配一个类型/特征并覆盖其类型派生自/实现这种类型/特征的所有对象,特征是Seq,并且类型参数是事先已知的。 因为我是scala新手,所以我很困惑。

想法?

2 个答案:

答案 0 :(得分:5)

由于类型擦除,您无法检查参数化类型。看到这个问题,为什么会有警告:Warning about an unchecked type argument in this Scala pattern match?

另一个问题及其答案告诉您如何解决这个问题:How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?

然而,当您不检查类型参数时,您的代码可以正常工作:

scala> List("a") match { case _: Seq[_] => 1 case _ => 2 }
res0: Int = 1

答案 1 :(得分:1)

我的第一个想法是你做错了。你想要的不是模式匹配,而是一个类型类,或者一些其他可以进行基于类型的动态调度的机制(类方法)。使用模式匹配来执行您自己的基于类型的调度会导致代码混乱并阻止类型安全。

这是Scala中类型类的快速常见示例。首先,定义类型类共有的特征:

trait Ord[T] { def compare (x: T, y: T): Boolean }

在您的情况下,您希望a方法成为特征的方法。然后,对于您想要属于类型类的每种类型,为其创建一个隐式对象:

implicit object ordInt extends Ord[Int] {
  def compare (x: Int, y: Int) = x <= y
}

在这里,我已将Int作为Ord类型类的实例。现在,您可以编写依赖于类型类提供的接口的方法。该方法应该隐式接受特定类型类对象,如下所示:

def sort[T](xs: List[T])(implicit ord: Ord[T]) = {

然后,您可以通过在隐式对象上调用它来使用类型类上的特殊方法。

def sort[T](xs: List[T])(implicit ord: Ord[T]) = {
  def insert(y: T, ys: List[T]): List[T] = ys match {
    case Nil => List(y)
    case z :: zs =>
      if (ord.compare(y,z)) { y::z::zs } // <--- here I use ord.compare
      else { z :: insert(y, zs) }
  }
  xs.foldRight(List[T]())(insert _)
}

瞧!我们有类型导向调度,不会丢失类型安全性。想要排序Ints列表?没问题。试图对没有Ord实例的事物列表进行排序?编译器会阻止你在脚下射击。