【问题标题】:Calling overloaded super constructor in ScalaJS class that extends a native class在扩展本机类的 ScalaJS 类中调用重载的超级构造函数
【发布时间】:2016-03-06 15:38:35
【问题描述】:

我有这个 JavaScript 类/构造函数:

function Grid(size, tileFactory, previousState, over, won) {
    this.size        = size;
    this.tileFactory = tileFactory;
    this.cells       = previousState ? this.fromState(previousState) : this.empty();
    this.over        = over ? over : false;
    this.won         = won ? won : false;
}

我使用这个 ScalaJS 外观进行了映射:

@js.native
class Grid[T <: Tile](val size: Int,
                      val tileFactory: TileFactory[T],
                      previousState: js.Array[js.Array[TileSerialized]],
                      val over: Boolean,
                      val won: Boolean) extends js.Object {

  val cells: js.Array[js.Array[T]] = js.native

  def this(size: Int, tileFactory: TileFactory[T]) = this(???, ???, ???, ???, ???)

  ...

}

我想扩展 Grid 类,我已经这样做了:

@ScalaJSDefined
class ExtendedGrid(
                    override val size: Int,
                    override val tileFactory: TileFactory[Tile],
                    previousState: js.Array[js.Array[TileSerialized]],
                    override val over: Boolean,
                    override val won: Boolean) extends Grid(size, tileFactory, previousState, over, won) {

  ...

}

但是现在我还需要为这个ExtendedGrid 类实现重载的构造函数。

问题是,我该怎么做?


理想情况下,我想做这样的事情:

def this(size: Int, tileFactory: TileFactory[Tile]) = super(size: Int, tileFactory: TileFactory[Tile])

但据我了解,这在 Scala 中是不可能的。

只是为了尝试一下,我试图简单地复制我在外观中定义的原始重载构造函数:

def this(size: Int, tileFactory: TileFactory[T]) = this(???, ???, ???, ???, ???)

确实编译但显然导致浏览器错误:

Uncaught scala.NotImplementedError: an implementation is missing

然后我尝试了:

def this(size: Int, tileFactory: TileFactory[Tile]) = this(size, tileFactory, this.empty(), false, false)

模仿原始 JavaScript 函数的行为但无济于事。它会产生这个错误:

this can be used only in a class, object, or template

【问题讨论】:

    标签: javascript scala scala.js


    【解决方案1】:

    您尝试调用的构造函数没有真的 重载。它更接近于具有可选值的 默认参数。在 JS 中,默认参数基本都是undefined。所以你可以对父构造函数进行不同的建模:

    @js.native
    class Grid[T <: Tile](val size: Int,
                          val tileFactory: TileFactory[T],
                          previousState: js.UndefOr[js.Array[js.Array[TileSerialized]]] = js.undefined,
                          _over: js.UndefOr[Boolean] = js.undefined,
                          _won: js.UndefOr[Boolean] = js.undefined) extends js.Object {
      val over: Boolean = js.native
      val won: Boolean = js.native
      val cells: js.Array[js.Array[T]] = js.native
    
      ...
    }
    

    然后你可以在定义你的类时模仿同样的结构:

    @ScalaJSDefined
    class ExtendedGrid(size: Int,
                       tileFactory: TileFactory[Tile],
                       previousState: js.UndefOr[js.Array[js.Array[TileSerialized]]] = js.undefined,
                       _over: js.UndefOr[Boolean] = js.undefined,
                       _won: js.UndefOr[Boolean] = js.undefined) extends Grid(size, tileFactory, previousState, _over, _won) {
    
      ...
    
    }
    

    顺便说一句,不要使用override val,因为您将值传递给父构造函数,并且您从超类中获得了val

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 2023-03-26
      • 2017-09-07
      • 2018-09-26
      • 2014-04-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多