【问题标题】:Early return from parent AND child method从父子方法提前返回
【发布时间】:2021-11-18 15:50:00
【问题描述】:

我在 ES6 中有一个这样的基类:

class BasePlot {
  props = {
    'data': []
  }

  constructor() { 
    // do things but don't setup data
  }

  draw(data){
    if (data && data.length )
      this.props.data = data;
    // Q: how to exit here if height and width are not yet available?
    this.setScale()
    this.setAxis()
  }

  setDimensions(height, width) {
    this.props.height = height;
    this.props.width = width;
  }
}

该类永远不会被直接实例化,而只会用于继承。
除了构造函数之外,所有其他方法都可能以不可预知的顺序调用,这就是为什么在 draw 方法中,如果尚未为实例定义 heightwidth,我不想继续。

我可以简单地添加一个if 条件并退出,但这不是我的想法。

在子类中,我这样称呼父类draw

class RectPlot extends BasePlot{ 
  draw(data){
    super.draw(data);
    // DON'T EXECUTE if height and width are not set
    // rest of the code
  }
}

在这种情况下,当我调用子 draw 时,我首先调用父方法,如果尚未设置 heightwidth,我想从父方法退出(返回)但是来自孩子。

我的意思是,是这样的:

// Parent
draw(data){
  if (data && data.length )
    this.props.data = data;
    if(this.props.height && this.props.width)
      this.setScale()
      this.setAxis()
      return true
    }
    else return false
  }
}

// Child
draw(data){
  if(super.draw(data)){
    // proceed w rest of the code
  }
  else return false
}

这正是我想做的,除了我不想检查所有子类中的 if 是否父 draw 成功完成。

问:除了前面提到的在所有子类中重复 if-else 块之外,还有其他方法可以“提前退出”父和子方法吗?

【问题讨论】:

  • 这都是可视化的,但也许如果你不使用if (blah) {..} else return false;,你会使用if (!blah) return false;,这将是一个更清晰的代码......

标签: javascript inheritance ecmascript-6 es6-class


【解决方案1】:

您不能从被调用方法中的调用者方法返回。但是,您可以完全避免这个问题...

另一种设计可能是创建另一种方法,例如drawCanvas,如下所示...

class BasePlot {
  props = {
    data: [],
  };

  draw(data) {
    if (data && data.length) this.props.data = data;
    if (this.props.height && this.props.width) this.drawCanvas(data);
  }

  drawCanvas(data) {
    this.setScale();
    this.setAxis();
  }
}

class RectPlot extends BasePlot {
  drawCanvas(data) {
    super.drawCanvas(data);
    // other stuff
  }
}

然后,您将覆盖drawCanvas 而不是draw,因为知道drawCanvas 仅在widthheight 存在时才被调用。

我同意检查 super.draw(data) 的返回值,如您的示例所示,并不理想。很容易忘记此检查,从而导致潜在的错误。对于子类实现的读者来说,为什么不看基类实现就需要这个检查也不是很明显。

【讨论】:

  • 我认为这不会有帮助,因为我需要一直执行父 draw 的第一步,即设置数据。然后第二步是可选的,取决于是否已经设置了高度和宽度。按照您的逻辑,父 drawCanvas 应该调用 draw,我们将回到第一方。
  • @Leonardo drawCanvas 不应调用draw,因为那样它会无限递归并崩溃。在上面的示例中,父 drawCanvas 由子 drawCanvas 调用,子 drawCanvas 仅在设置了高度和宽度时才从父 draw 调用。因此,第一步设置始终由draw 执行,第二步由drawCanvas 可选执行,符合您的要求。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
相关资源
最近更新 更多