无法将PartialFunction放入Scala类构造函数中

7

似乎有一个限制,即您不能在类构造函数中使用PartialFunction字面量:

scala> case class X(a: PartialFunction[Any, Any]) { def this() = this({case x => x}) }
<console>:7: error: Implementation restriction: <$anon: Any => Any> requires premature access to class X.
   case class X(a: PartialFunction[Any, Any]) { def this() = this({ case x => x}) }

我的第一个问题是,为什么部分类函数需要访问"this"。第二个问题/观察结果是,在Scala REPL中,再次运行相同的代码会导致REPL崩溃:

scala> case class X(a: PartialFunction[Any, Any]) { def this() = this({ case x => x}) }
java.lang.NullPointerException
    at scala.tools.nsc.Global$Run.compileLate(Global.scala:1595)
    at scala.tools.nsc.GlobalSymbolLoaders.compileLate(GlobalSymbolLoaders.scala:29)
    at scala.tools.nsc.symtab.SymbolLoaders$SourcefileLoader.doComplete(SymbolLoaders.scala:369)
    ...

最后,有没有一个好的解决方法来解决这个问题?

1
请参见SI-8593。另外相关链接:https://groups.google.com/forum/#!topic/scala-user/V085Tg0mKcU - Michael Zajac
2个回答

7

你的第一个问题在此问题的评论部分中得到了回答。

引用Imm的话:

匿名类可以访问它们的封闭类。编译器不知道你的匿名局部函数实际上并没有访问任何东西(在完全通用性方面检查这一点非常困难);它只是禁止在进入类之前创建任何匿名类。

为什么会崩溃REPL是一个好问题,你应该向Typesafe提交带有此代码示例的票据。

解决方法非常简单,只需将匿名函数定义在类外部,这样编译器就知道你正在关闭的确切状态:

object X {
  val Default: PartialFunction[Any, Any] = { case x => x }
}

case class X(a: PartialFunction[Any, Any]) {
  def this() = this(X.Default)
}

1

你的第一个问题已经在此问题的评论部分中得到了回答。

问题在于编译器过于严格,因为它不知道如何将内容从构造函数参数块中提取出来。

另一个答案中给出了解决方法,这也是编译器应该使用的方法。

另一个解决方法是手动构建:

case class X(a: PartialFunction[Any, Any]) { def this() = this({
    class $anonfun extends runtime.AbstractPartialFunction[Any, Any] {
      override def applyOrElse[A, B >: Any](x: A, default: A => B): B = x match {
        case x => x
        //case _ => default(x) // completeness
      }
      override def isDefinedAt(x: Any) = x match {
        case x => true
        //case _ => false
      }
    }
    new $anonfun()
  })
}

你第二个问题的答案是SI-9170,已在2.11.7版本中修复。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接