是否可以忽略仅JVM属性并安全地导出到JavaScript?

时间:2016-02-11 04:21:37

标签: scala.js

我有Play with ScalaJS example之后的基本项目设置。我发现使用相同模式的其他示例将案例类(模型)与传统上它们的伴随对象分开。也就是说,案例类将存在于“共享”子项目中,而“伴随对象”(实际上只是某个对象)将存在于“服务器”子项目中。

最好将这两个文件保存在同一个文件中(即将重要内容放在真正的伴随对象中),因为在那里放置类型类实例并让它们正确解析是非常方便的。例如:

case class User(id: Int, name: String)

object User {

  val default = User(1, "Guest")

  // I need this for the back-end, but don't need to export to JS
  implicit val reads: Reads[User] = ...
}

不幸的是,这会导致链接错误,因为Reads类型仅存在于JVM上(只是其中之一)。但是,如果我将val reads移动到另一个文件中,Reads[User]的隐式解析将在整个“服务器”子项目中中断,而不会添加显式导入(这会令人讨厌)。

是否可以显式忽略ScalaJS导出中的某些属性,同时仍允许它们为JVM编译?我希望导出User案例类,甚至可能导出其伴随对象的其他属性,但只能忽略JVM上存在的其他属性而不会中断前端。

1 个答案:

答案 0 :(得分:3)

我在过去(在Scala.js代码库本身中)解决这个问题的方式是将PlattformExtensions特性混合到交叉编译对象中,但对于JVM和JS来说是不同的:

object User extends UserPlattformExtensions {
  val default = User(1, "Guest")
}

在您的JVM项目中:

trait UserPlattformExtensions {
  implicit val reads: Reads[User] = ???
}

在你的JS项目中:

trait UserPlattformExtensions

在您的文件组织中(使用标准交叉项目),这将如下所示:

project/
  shared/
    src/main/
      User.scala
  jvm/
    src/main/
      UserPlattformExtensions.scala
  js/
    src/main/
      UserPlattformExtensions.scala

没有依赖性问题,因为对于编译器,源文件按如下方式汇编:

sources in projectJVM:
  shared/src/main/User.scala
  jvm/src/main/UserPlattformExtensions.scala

sources in projectJS:
  shared/src/main/User.scala
  jvm/src/main/UserPlattformExtensions.scala

因此,对于每个单独的编译运行,整个构造只是一个从特征继承的对象。源代码来自哪些源目录与编译无关。