javascript - 如何使 ES6 类最终(不可子类化)

标签 javascript ecmascript-6 ecmascript-next

假设我们有:

class FinalClass {
  ...
}

如何修改它以使
class WrongClass extends FinalClass {
  ...
}

或者
new WrongClass(...)

生成异常?也许最明显的解决方案是在 FinalClass 的构造函数中执行以下操作:
if (this.constructor !== FinalClass) {
    throw new Error('Subclassing is not allowed');
}

有没有人有更清洁的解决方案,而不是在每个应该是最终的类中重复这些行(可能使用装饰器)?

最佳答案

检查this.constructorFinalClass 的构造函数中如果它不是它自己,则抛出。 (借用检查 this.constructor 而不是 this.constructor.name 来自@Patrick Roberts。)

class FinalClass {
  constructor () {
    if (this.constructor !== FinalClass) {
      throw new Error('Subclassing is not allowed')
    }
    console.log('Hooray!')
  }
}

class WrongClass extends FinalClass {}

new FinalClass() //=> Hooray!

new WrongClass() //=> Uncaught Error: Subclassing is not allowed


或者,在支持下,使用 new.target .谢谢@loganfsmyth。

class FinalClass {
  constructor () {
    if (new.target !== FinalClass) {
      throw new Error('Subclassing is not allowed')
    }
    console.log('Hooray!')
  }
}

class WrongClass extends FinalClass {}

new FinalClass() //=> Hooray!

new WrongClass() //=> Uncaught Error: Subclassing is not allowed


______

正如您所说,您也可以使用装饰器来实现此行为。

function final () {
  return (target) => class {
    constructor () {
      if (this.constructor !== target) {
        throw new Error('Subclassing is not allowed')
      }
    }
  }
}

const Final = final(class A {})()

class B extends Final {}

new B() //=> Uncaught Error: Subclassing is not allowed



正如 Patrick Roberts 在评论中分享的装饰器语法 @final仍在提案中。它适用于 Babel 和 babel-plugin-transform-decorators-legacy .

关于javascript - 如何使 ES6 类最终(不可子类化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38748325/

相关文章:

javascript - React/Redux - 为什么我的操作/ reducer 不工作?

javascript - 在 typescript 中应该定义什么类型的超时

javascript - async/await 隐式返回 promise ?

javascript - 如何在scss中使用if else条件

javascript - 导航栏过渡 CSS 问题

javascript - JSON从php到JS文件

parameters - 带有 Babel 的参数装饰器(如在 Typescript 中)

javascript - 导入 ES6 风格,如 * 但用于一组 const 以避免重复

javascript - 在 babeljs 中连接模块中的导入

javascript - 接下来ES中的对象映射