【问题标题】:Scala erasure class type parameterScala 擦除类类型参数
【发布时间】:2014-11-08 07:30:17
【问题描述】:

我有以下设置:

class Test[A](function: A => String) {
   def process(data: Any) {         //has to be Any since it is user IO
      if (data of Type A) 
          function(data)
   }
}

我似乎无法让类型检查工作。 我尝试将隐式 TypeTag 添加到 Test[A] 但我无法从进程中访问它。 是否可以在过程函数中匹配Test的类型参数?

【问题讨论】:

    标签: scala type-parameter erasure


    【解决方案1】:

    为此使用ClassTag 和match:

    import scala.reflect.ClassTag
    
    class Test[A : ClassTag](function: A => String) {
      def process(data: Any) { //has to be Any since it is user IO 
        data match {
          case data: A => function(data)
          case _       =>
        }
      }
    }
    

    由于作用域中隐含的ClassTag,match 可以区分A,即使它是通用的。

    【讨论】:

    • 非常好!我很接近 :-) 但不是很接近
    • 其实不行。它在没有警告的情况下编译,但在运行时用例数据期间:A 匹配任何内容
    【解决方案2】:

    使用Shapeless:

      class Test[A: Typeable](function: A => String){
        import shapeless.syntax.typeable._
        def process(data: Any) {         //has to be Any since it is user IO
          data.cast[A] map { function(_) }
        }
      }
    

    这个是安全的,因为它返回一个 Option[A],所以当转换失败时,你可以在 None 上进行模式匹配。

    【讨论】:

    • 感谢您的回答!标准库中是否有任何东西可以实现相同的功能?
    • “标准库”(data.isInstanceOf[A] 和 data.asInstanceOf[A])只能部分工作 - 直到擦除。所以你将无法匹配List[Int] 与List[String],它只会是List[_],可能会导致instanceOf 和ClassCastException 在运行时出现误报。
    • 使用较新的 scala 版本,您可以使用捕获完整类型的 TypeTags:scala-lang.org/files/archive/nightly/docs/library/… 我似乎无法让它工作。
    【解决方案3】:

    我不确定为什么 data 必须是 Any 类型(用户输入不是 String 类型吗?),但如果确实如此,那么它可能反映了类型在编译时无法预料。在这种情况下,您可能希望该方法在尝试强制转换时抛出运行时错误:

    class Test[A](function: A => String) {
       def process(data: Any) = {
          function(data.asInstanceOf[A]) //might throw an error
       }
    }
    

    或者可能使用Try monad:

    class Test[A](function: A => String) {
       def process(data: Any) = {
          Try(function(data.asInstanceOf[A]))
       }
    }
    

    当然最好在编译时知道data的类型:

    class Test[A](function: A => String) {
       def process(data: A) = {
          function(data)
       }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-05-28
      • 2012-12-30
      • 2020-07-27
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多