【问题标题】:Getting around a type-erasure in pattern-matching绕过模式匹配中的类型擦除
【发布时间】:2011-04-14 16:35:17
【问题描述】:

我正在尝试解决模式匹配中的类型擦除问题。假设:

import java.io._

trait Serializer[V] {
  def save(os: OutputStream, v: V): Unit
  def load(in: InputStream): V
}

trait HasSerializer[V] { def serializer: Serializer[V] }

如何在没有警告和asInstanceOf 的情况下编译它:

def test[V](os: OutputStream, v: V): Unit = v match {
  case hs: HasSerializer[V] => hs.serializer.save(os, v)
  case _                    => ???
}

test 是使用映射中的值调用的,无法提供类清单。

可能有什么花哨的提取技巧吗?

【问题讨论】:

    标签: scala pattern-matching type-erasure


    【解决方案1】:

    如果您可以将 Serializer 设为抽象类,则可以将 Manifest 作为隐式构造函数参数,并在构造时使用它来获取具体类,然后稍后将其用于动态类型检查。

    import java.io._
    
    abstract class Serializer[V: Manifest] {
      def save(os: OutputStream, v: V): Unit
      def load(in: InputStream): V
      val clazz = manifest[V].erasure
    }
    
    val ser = new Serializer[Int] {
      def save(os: OutputStream, v: Int) {
        os.write((v.toString + "\n").getBytes)
      }
    
      def load(in: InputStream) = {
        val line = new BufferedReader(new InputStreamReader(in)).readLine()
        line.toInt
      }
    }
    
    ser.clazz //  java.lang.Class[_] = int
    

    【讨论】:

    • 但是我如何知道 V 的实例是否提供了序列化器?我仍然看不到如何在 test 方法中执行检查,而无需最终强制转换为 V
    • 如果你不能使用类型类,因为值本质上是无类型的,我不确定你是否可以避免使用一些注册表和查找机制。不过,我很高兴看到另一种方法!
    • 我不需要注册表,因为我可以匹配HasSerializer[ _ ],然后安全地转换为HasSerializer[ V ],但这正是我不想做的。 V 在不同的接口之间传递了几次,传递 ClassManifest 根本没有选择,Scala 只是老实说这个“物化”的概念很糟糕......
    【解决方案2】:

    这个问题有一个错误的前提条件(正如我刚刚意识到的那样)——我们可以将Serializer 分解为一个序列化器和一个反序列化器。显然,当我有V 的实例时,我的用例是序列化,并且不需要V 作为返回类型。因此

    trait Serializer { def save(os: OutputStream): Unit }
    

    就足够了,任何类型都可以混合使用。然后做:

    def testSer[V](os: OutputStream, v: V): Unit = v match {
      case s: Serializer => s.save(os)
      case _ => new ObjectOutputStream(os).writeObject(v)
    }
    

    对于反序列化,我们将提供反序列化器以及 Ref[V] 的构造,或者依赖通过 ObjectInputStream 进行的类查找。

    【讨论】:

    • 好吧,“任何类型都可以混合它”当然不是真的。对于现有类型,问题仍然存在,假设(如 Alex 的示例中)我们想为 Int... 提供序列化程序...
    猜你喜欢
    • 2015-11-21
    • 2017-11-23
    • 1970-01-01
    • 2018-04-12
    • 2015-10-06
    • 2023-03-31
    • 2016-01-24
    • 2015-08-18
    • 2013-09-07
    相关资源
    最近更新 更多