首页 文章

在模式匹配中绕过类型擦除

提问于
浏览
6

我试图在模式匹配中解决类型擦除问题 . 假设:

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 _                    => ???
}

?使用 Map 中的值调用 test ,并且无法提供类清单 .

任何花哨的提取器技巧可能吗?

2 回答

  • 4

    如果你可以使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
    
  • 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 的类查找 .

相关问题