【问题标题】:Scala type check / assertion as a function vs JVM type erasureScala 类型检查/断言作为函数与 JVM 类型擦除
【发布时间】:2017-07-20 14:46:32
【问题描述】:

我有一些代码通常会像这样进行类型检查:

obj match {
  case _: Foo =>
    // everything is fine
  case _ =>
    throw SomeException(...)
}

它可以工作,但它相对庞大,感觉就像是大量重复的代码(特别是考虑到异常需要大量参数),所以我认为它会取代这个断言函数。然而,我天真的尝试失败了:

def assertType[T](obj: CommonType): Unit = {
  obj match {
    case _: T =>
      // everything is fine
    case _ =>
      throw SomeException(...)
  }
}

显然,由于 JVM 类型擦除,这个 T 参数被忽略,所以第一个 case 分支始终为真。 ⇒ Full source code demonstrating the problem

当然,可以求助于 Java 的反射方法,但这种方法速度慢、丑陋且不可移植。在 Scala 中进行此类断言的首选方式是什么?

有些相关,但不解决这个确切的问题:

【问题讨论】:

  • 所以关键是要有一个抛出自定义异常的方法,而不是普通的ClassCastException?
  • @MichalM 是的,或多或少是这样。实际上,我正在编写一个需要更好的错误消息的编译器,而我做所有这些断言的地方是唯一有足够上下文来生成有意义的错误消息的地方(即带有行/列号等)。
  • 显然,shapeless 实现了类似的功能(我认为它仍然会抛出 ClassCastException),如您可能感兴趣的答案stackoverflow.com/a/8821911/1050787 所示。不幸的是,他们在github.com/milessabin/shapeless/blob/master/core/src/main/scala/… 中是如何做到的,我仍然无法理解,所以我只能给你链接......

标签: scala types pattern-matching


【解决方案1】:

也传递清单:

def assertType[T : Manifest](obj: CommonType): Boolean

然后您的示例代码将正常工作:

v1 is Foo = true
v1 is Bar = false
v2 is Foo = false
v2 is Bar = true

【讨论】:

  • 谢谢!这正是我一直在寻找的。你能给我一些指示,我可以在哪里阅读更多关于这个Manifest魔法的信息?
  • 这个post 有一些关于类型标签和清单的重要信息。清单最终会被弃用,取而代之的是 TypeTag,但它们更适合您的情况。
  • 事实证明 Manifest 确实已被弃用并且 Scala.js 不支持(我们也在交叉编译到 JS),但 ClassTag 似乎也能很好地完成这项工作,所以我最终使用了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 2012-12-30
  • 1970-01-01
  • 2020-07-27
  • 2012-08-12
相关资源
最近更新 更多