部分功能匹配类型擦除类型

时间:2015-10-13 13:58:49

标签: scala pattern-matching type-erasure

在以下代码中,我希望仅在hitA的类型为i时才调用A。要检查的类型是作为类型参数提供的,因此它被类型擦除并且match失败,给我一个编译器警告:

  

抽象类型模式T未被选中,因为它被擦除

代码的所需输出是:

  

点击A

     

未点击

在我运行代码的当前版本中,我得到了命中A,然后是ClassCastException

我理解发生了什么以及警告和例外的原因,但我不知道如何解决这个问题。我已经阅读了有关TypeTags的基本文章,并且我理解如何在基本情况下使用它们,但我没有看到如何使用TypeTags创建部分函数。

import scala.reflect.runtime.universe._


object TestMatch extends App {
  abstract class I

  class A extends I {
    def hitA() = println("Hit A")
  }

  class B extends I

  def processOpGen[T <: I : TypeTag](op: PartialFunction[I, Unit])(i: I) = {
    val fallback : PartialFunction[I, Unit] = {case _ => println("Not hit")}
    (op orElse fallback)(i)
  }

  def partialMatchGen[T <: I : TypeTag](op: T => Unit)(i: I) = {
    processOpGen[T] {
      case c: T => op(c) // can TypeTag be used here for matching somehow?
    }(i)
  }


  partialMatchGen[A](a => a.hitA())(new A)
  partialMatchGen[A](a => a.hitA())(new B)

}

1 个答案:

答案 0 :(得分:2)

只需replace TypeTag with ClassTag

import scala.reflect._

object Main extends App {
  abstract class I

  class A extends I {
    def hitA() = println("Hit A")
  }

  class B extends I

  def processOpGen[T <: I : ClassTag](op: PartialFunction[I, Unit])(i: I) = {
    val fallback : PartialFunction[I, Unit] = {case _ => println("Not hit")}
    (op orElse fallback)(i)
  }

  def partialMatchGen[T <: I : ClassTag](op: T => Unit)(i: I) = {
    processOpGen[T] {
      case c: T => op(c) // can TypeTag be used here for matching somehow?
    }(i)
  }

  partialMatchGen[A](a => a.hitA())(new A)
  partialMatchGen[A](a => a.hitA())(new B)
}

Processing...
Reused last reload result
[info] Loading project definition from /tmp/rendererL3zBdh8HOA/project/project
[info] Loading project definition from /tmp/rendererL3zBdh8HOA/project
[info] Set current project to rendererWorker (in build file:/tmp/rendererL3zBdh8HOA/)
[info] Reapplying settings...
[info] Set current project to rendererWorker (in build file:/tmp/rendererL3zBdh8HOA/)
[info] Formatting 1 Scala source {file:/tmp/rendererL3zBdh8HOA/}rendererWorker(compile) ...
[warn] Scalariform parser error for /tmp/rendererL3zBdh8HOA/src/main/scala/test.scala: Expected token RBRACKET but got Token(XML_START_OPEN,<,335,<)
[info] Compiling 1 Scala source to /tmp/rendererL3zBdh8HOA/target/classes...
[success] Total time: 11 s, completed Oct 13, 2015 5:16:45 PM
Now running...
[info] Running Main 
Hit A
Not hit
[success] Total time: 0 s, completed Oct 13, 2015 5:16:45 PM