Scala.js 平台相关方法实现(或依赖注入)

2 scala.js

tl;dr:像 scalajs-java-time 这样的库如何替换依赖项?

我在 Scala.js 中遇到了这种依赖注入:

在共享代码中:

object Example {
  def method(...) = { ... dependsOnPlatform ... }
  val dependsOnPlatform = ???
}
Run Code Online (Sandbox Code Playgroud)

这样做的天真的方法是:

val dependsOnPlatform = if(onJS) jsImplementation else jvmImplementaion
Run Code Online (Sandbox Code Playgroud)

问题是,通常无法jsImplementation针对 JVM 进行编译,因为它依赖于 Scala.js 类;如果使用反射或引用 Java 类,则可能无法完成fastOptJSjvmImplementaion

鉴于它object Example必须是静态的,因此不能使用构造函数注入。

用反射来解决这个问题很容易,但同样在 Scala.js 中是不允许的。
虽然有副作用,但它可以解决,但由于对象是静态的,所以这会很脆弱。
依赖项可以是 的隐式参数method,但这需要额外的导入。
这不是宏可以在不使构建过程复杂化的情况下解决的问题。

sjr*_*jrd 6

js/src/推荐的解决方案是使用在中 与 中中实现不同的顶级对象jvm/src/,但向两者公开相同的接口。然后可以从shared/src/代码中正常使用该对象的 API。该对象通常被调用Platform并设为包私有。

js/src/.../Platform.scala

package foo

private[foo] object Platform {
  def dependsOnPlatform(...) = {
    jsImplementation
  }
}
Run Code Online (Sandbox Code Playgroud)

jvm/src/.../Platform.scala

package foo

private[foo] object Platform {
  def dependsOnPlatform(...) = {
    jvmImplementation
  }
}
Run Code Online (Sandbox Code Playgroud)

shared/src/.../Platform.scala

package foo

object Example {
  def method(...) = {
    ...
    Platform.dependsOnPlatform(...)
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

不需要使用丑陋的“shadowing” hack,也不需要编写 .java 源文件,如 @acdenh 的答案中所述。