用特征中的抽象类型解决类型擦除问题

时间:2014-08-19 07:54:45

标签: scala scala-2.10 type-erasure

我有这样的情况:

import scala.reflect._

trait SomeTrait {
  type T
  implicit def tag: ClassTag[T]
  def func2(x: Any) = x match {
    case x: T => "foo"
    case _ => "bar"
  }
}

case class SomeCaseClass()

class SomeClass extends SomeTrait {
  type T = SomeCaseClass
  implicit def tag = scala.reflect.classTag[SomeCaseClass]
  val x = SomeCaseClass()
  def func1() = func2(x)
}

object Main extends App {
  val someClass = new SomeClass()
  someClass.func1()
}

但是,someClass.func1()调用会产生

java.lang.StackOverflowError
  at SomeClass.tag(...)
  at SomeClass.tag(...)
  at SomeClass.tag(...)
  //etc.
好像它递归地调用自己一样。如果我删除ClassTag,那么我有类型擦除警告,我需要修复它。另外,我需要SomeTrait保持特征,因此[T : ClassTag]作为类型参数不是一个选项。有谁知道如何在特征中使用抽象类型来避免类型擦除警告?

1 个答案:

答案 0 :(得分:3)

请参阅reflect api

 
def classTag[T](implicit ctag: ClassTag[T]): ClassTag[T]

致电时:  

implicit def tag = scala.reflect.classTag[SomeCaseClass]

你的执行是:  

implicit def tag = scala.reflect.classTag[SomeCaseClass](tag)

你会收到永无止境的循环。

尝试(在对象中,SomeCase隐式不可见):

 
object SomeCase {
  val tagSomeCaseClass =  scala.reflect.classTag[SomeCaseClass]
}


class SomeClass extends SomeTrait {
  type T = SomeCaseClass
  implicit def tag = SomeCase.tagSomeCaseClass
  val x = SomeCaseClass()
  def func1() = func2(x)
}

我检查过 - 它对我有用:  阶> val someClass = new SomeClass()         someClass:SomeClass = SomeClass @ 371a67ec

    scala> someClass.func1()
    res0: String = foo

    scala> someClass.func2(4)
    res1: String = bar

    scala> someClass.func2("String")
    res2: String = bar

    scala> someClass.func2(SomeCaseClass())
    res3: String = foo

我不知道如何压制警告......