scala - 为什么Scala PartialFunction isDefinedAt 方法总是返回true?
问题描述
我的代码如下。
case class C[T]() {
val pf:PartialFunction[Any,Any] = {
case i:T => i
}
}
println(C[Int]().pf.isDefinedAt(-1.0))
这打印true
。为什么会发生这种情况?
解决方案
由于类型擦除,您的代码基本上等于:
case class C[T]() {
val pf:PartialFunction[Any,Any] = {
case i:Any => i // this matches everything
}
}
您可以使用TypeTag
s 来修复它:
import scala.reflect.runtime.universe._
case class C[T: TypeTag]() {
def pf[U: TypeTag]: PartialFunction[U, Any] = {
case i if typeOf[U] <:< typeOf[T] => i
}
}
正在使用:
@ C[Int]().pf.isDefinedAt("")
res41: Boolean = false
@ C[Int]().pf.isDefinedAt(34)
res42: Boolean = true
这些实际上等于
@ C[Int]().pf[String].isDefinedAt("")
res41: Boolean = false
@ C[Int]().pf[Int].isDefinedAt(34)
res42: Boolean = true
推断类型U
的地方 - 它有一个限制,即它只能在需要时与编译器对类型的了解一样精确TypeTag
。
您也可以尝试ClassTag[T]
使用运行时反射......但对于原语它会失败
case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
def pf[U: TypeTag]: PartialFunction[U, Any] = {
case i if classTag.runtimeClass.isInstance(i) => i
}
}
这导致
@ C[Int]().pf.isDefinedAt(34)
res2: Boolean = false
@ C[Int]().pf.isDefinedAt("")
res3: Boolean = false
事情classTag
会解决 Scala 的int
,而运行时会显示java.lang.Int
:
@ case class C[T]()(implicit classTag: scala.reflect.ClassTag[T]) {
def pf: PartialFunction[Any, Any] = {
case i => println(s"T = ${classTag.runtimeClass.getName}, here: ${i.getClass.getName}")
}
}
defined class C
@ C[Int]().pf.isDefinedAt(34)
res7: Boolean = true
@ C[Int]().pf(34)
T = int, here: java.lang.Integer
res8: Any = ()
推荐阅读
- r - 如何使用方法='黄土'和公式'y〜x'关闭消息“`geom_smooth()`”
- html - 如何用 CSS 中的图像和导航解决这个问题
- c++ - Using #ifdef preprocessor around virtual functions causes runtime error in program linked against libraries
- java - Spring Webflux 2.5.x + Spring Cloud + Zipkin:无法获取 Zipkin 指标
- python - VS Code:如何通过launch.json中的shell命令获取进程ID?
- javascript - 承诺链不会等到其他承诺解决
- c - 我可以找到 Mac 线程中当前使用了多少堆栈内存吗?
- ruby-on-rails - rails 请求日志和 chrome 网络选项卡之间的延迟差异
- javascript - Angular 动态 html 只需单击一个按钮
- jmeter - 我收到与请求中的会话不匹配的令牌错误