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

发布于 2024-11-01 08:10:31 字数 535 浏览 3 评论 0原文

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

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 使用映射中的值进行调用,并且无法提供类清单。

也许有什么奇特的提取技巧?

I am trying to work around a type erasure in pattern matching. Assuming:

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] }

How can I get this to compile without warning and without asInstanceOf:

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

? test is called with a value from a map and there is no means to provide a class manifest.

Any fancy extractor trick maybe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

活雷疯 2024-11-08 08:10:31

如果您可以将 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

If you can make Serializer an abstract class instead, you can give it a Manifest as an implicit constructor parameter, and use that to get the concrete class at construction, then use it later for dynamic type checks.

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
掐死时间 2024-11-08 08:10:31

好吧,这个问题有一个错误的前提条件(正如我刚刚意识到的那样)——我们可以将 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。

Well the question has kind of a wrong precondition (as I just realize) -- we can take Serializer apart into a serializer and a deserializer. Obviously, when I have an instance of V, my use case is serialization, and that doesn't require V as a return type. Thus

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

would suffice, and any type can mix that in. And do:

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

And for deserialization, we would either provide the deserializer along with the construction of a Ref[V], or rely on class lookup through ObjectInputStream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文