【问题标题】:Concrete and abstract definitions in Scala.js facadesScala.js 外观中的具体和抽象定义
【发布时间】:2016-08-30 04:10:40
【问题描述】:

documentation 里有说

在原生 JS 类型中,所有具体定义必须以 = js.native 作为主体。任何其他主体都将像 = js.native 一样被处理,并且会发出警告。 (在 Scala.js 1.0.0 中,这将成为错误。)

这是正确的。但是我发现我完全可以省略body(从而使定义抽象)并且没有警告并且生成的js似乎与js.nativebody相同。

所以我的问题是:js.native body 的抽象定义和具体定义有什么区别?

【问题讨论】:

    标签: scala.js


    【解决方案1】:

    区别在于抽象定义是抽象的,而具体定义(= js.native)是具体的,从 Scala 的类型系统的角度来看。

    然后呢?从类或特征的 use 站点来看,并没有什么不同。这类似于普通的 Scala(或 Java):使用方法时,它是否是抽象的并不重要。

    所以真正的区别在于定义站点。理论上,选择抽象还是具体归结为这个标准:

    • 此方法在 JavaScript 代码中是否有实际的实现(不仅仅是文档化的合同)?如果是,它应该是具体的;如果不是,它应该是抽象的。

    实事求是,注意抽象方法只能出现在抽象类或特征中,并且必须在子类/子特征中实现。

    就外观而言,在本机类中,大多数方法应该是具体的(如果不是全部的话)。那是因为在 JS 中,类通常有具体的方法。事实上,abstract 方法在 JS 中甚至都不存在。在本机类中定义抽象方法的唯一合理情况是,如果该类的“合同/文档”规定 a) 它应该是子类,并且 b) 子类应该实现特定的方法(不在超类中实现)。这个记录在案的契约与 JS 可以达到的抽象方法一样接近。

    在 JS traits 中,方法通常应该是抽象的(并且 trait 本身是 @ScalaJSDefined 而不是 @js.native)。那是因为特性/接口本身在 JS 中甚至都不存在。它们只存在于其文档化的合同中,合同规定了满足此接口的类必须/将要实现哪些方法。

    (@js.native) JS 特征中具体方法的唯一合理用例是用于 DRYness。如果原生 API 的多个类实现了相同(大)的一组方法,那么将这些方法收集到原生 trait 中是合理的。为了不必在所有类中重复它们的定义,它们可以在 trait 中具体化(如果它们是抽象的,类将需要提供一个具体的版本来满足契约)。请注意,非原生 (@ScalaJSDefined) JS 类无法扩展此类特征。

    如果您不想弄清楚上述“理论”标准,请使用以下经验法则:

    • 该方法是否在原生 JS 类中?如果是,那几乎可以肯定是具体的。
    • 它在 JS 特征中吗?如果是,它几乎肯定是抽象的(特征应该是@ScalaJSDefined)。

    【讨论】:

      猜你喜欢
      • 2017-05-26
      • 2019-05-10
      • 1970-01-01
      • 2015-04-17
      • 2011-01-18
      • 2020-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多