8

我正在尝试让一个基本的 upickle 示例起作用,似乎我在这里遗漏了一些东西。我想试试upickle 自述页面上提供的示例

import upickle._

sealed trait A
@key("Bee") case class B(i: Int) extends A
case object C extends A

然后,我的代码是:

object Model {
  def main(args: Array[String]): Unit = {

    val a = B(5): A
    println(a)

    val out = write(a)
    println(out)

    val a2 = read[A](out)
    println(a2)

    println(a == a2)

  }
}

我得到的只是错误:

引用的特征 [[A]] 没有任何子类。这可能是由于 scalac (SI-7046) 的限制而发生的,因为该特征不在同一个包中。如果是这种情况,则可以使用整数常量来定义层次结构。

我有两个问题:

  • 如何让 uPickle 相信该特征在同一个包中?(因为它是。)
  • 或者如果我不能:如何使用整数常量定义层次结构?
4

2 回答 2

8

曾经有过这样的症状,您可以在这样的问题上花费数小时,然后在提出 StackOverflow 问题后几分钟就解决了它?

事实证明,由于特定于编译器的细节,这样的密封特征直到文件中定义它的点之后才会知道它的直接子类。因此,在这种情况下,我在 main 方法之后定义了 trait 及其案例,upickle 将在其中进行宏扩展和魔术。此时,它不会知道 trait 的情况。如果在定义 trait 及其案例之后将 main 方法移动到同一个文件中,它将起作用。

于 2015-02-20T14:18:27.167 回答
2

我在一个 Scala.js 项目中遇到了这个错误,我在服务器和客户端之间共享了一个密封的抽象类。

解决方案是使用Typelevel 编译器而不是默认的 Lightbend 编译器。

这很容易做到:

  1. 把它放在你的build.propertiessbt.version=0.13.13-M1
  2. 这在你的顶部build.sbtscalaOrganization in ThisBuild:= "org.typelevel"

为了完整起见,这是我现在可以在客户端和服务器之间共享的类:

sealed abstract class ServerResponse

case class Ok(msg: String) extends ServerResponse

case class Failure(msg: String) extends ServerResponse
于 2016-09-11T18:57:25.757 回答