我有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上存在的其他属性而不会中断前端。
答案 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
因此,对于每个单独的编译运行,整个构造只是一个从特征继承的对象。源代码来自哪些源目录与编译无关。