ES6类继承场景下如何实现父类与子类方法同时提前退出
解决方案
方案1:模板方法模式(最推荐)
把父类的draw方法作为统一流程入口,不允许子类重写,额外预留钩子方法供子类实现自定义逻辑,所有校验逻辑全部收敛在父类,子类无需额外判断。
实现代码
父类改造
class BasePlot { props = { data: [] } constructor() { // 初始化逻辑 } // 核心流程方法,禁止子类重写 draw(data){ if (data?.length) { this.props.data = data; } // 校验不通过直接终止所有逻辑 if (!this.props.height || !this.props.width) { return; } // 父类原有逻辑 this.setScale(); this.setAxis(); // 执行子类自定义逻辑 this.onDraw(); } // 钩子方法,子类按需重写,默认空实现 onDraw() {} setScale() { /* 原有逻辑 */ } setAxis() { /* 原有逻辑 */ } setDimensions(height, width) { this.props.height = height; this.props.width = width; } }
子类实现
class RectPlot extends BasePlot{ // 仅重写钩子方法,无需任何校验判断 onDraw(){ // 原子类draw中的剩余逻辑直接写在这里即可 // 只有父类校验通过时,该方法才会被触发 } }
如果要严格禁止子类重写draw方法,可在父类构造函数中添加如下代码:
constructor() { Object.defineProperty(this, 'draw', { value: this.draw.bind(this), writable: false, configurable: false }) }
方案2:自定义错误终止流程
如果业务要求必须保留子类重写draw的逻辑,可在校验不通过时抛出指定类型的自定义错误,在上层调用处统一捕获处理即可同时打断父子类的执行流程。
实现代码
// 自定义错误类 class DimensionsNotReadyError extends Error { constructor() { super('height and width are not initialized'); this.name = 'DimensionsNotReadyError'; } } // 父类draw改造 draw(data){ if (data?.length) { this.props.data = data; } if (!this.props.height || !this.props.width) { throw new DimensionsNotReadyError(); } this.setScale(); this.setAxis(); } // 上层调用处统一处理 try { const plot = new RectPlot(); plot.draw(data); } catch (e) { // 仅忽略尺寸未就绪的错误,其他错误继续抛出 if (e.name !== 'DimensionsNotReadyError') { throw e; } }
内容的提问来源于stack exchange,提问作者Leonardo
相关产品推荐
相关产品推荐

