javascript 如何使ES6类成为final(非子类)

pnwntuvh  于 2023-05-12  发布在  Java
关注(0)|答案(3)|浏览(209)

假设我们有:

class FinalClass {
  ...
}

如何修改它使

class WrongClass extends FinalClass {
  ...
}

new WrongClass(...)

来生成一个异常也许最明显的解决方案是在FinalClass的构造函数中执行以下操作:

if (this.constructor !== FinalClass) {
    throw new Error('Subclassing is not allowed');
}

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

nx7onnlm

nx7onnlm1#

检查FinalClass的构造函数中的this.constructor,如果它不是它本身,则抛出。(借用@帕特里克Roberts对this.constructor而不是this.constructor.name的检查。

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

正如帕特里克Roberts在评论中所分享的,装饰器语法@final仍在提议中。它可以在Babel和babel-plugin-transform-decorators-legacy中使用。

4smxwvx5

4smxwvx52#

constructor.name很容易被欺骗。只需使子类与超类同名即可:

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

const OopsClass = FinalClass

;(function () {
  class FinalClass extends OopsClass {}

  const WrongClass = FinalClass

  new OopsClass //=> Hooray!

  new WrongClass //=> Hooray!
}())

最好检查constructor本身:

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

const OopsClass = FinalClass

;(function () {
  class FinalClass extends OopsClass {}

  const WrongClass = FinalClass

  new OopsClass //=> Hooray!

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

bnlyeluc3#

假设你使用的是TypeScript,最简单的方法是将构造函数设置为private,如下所示:

class MyClass {

            private constructor() {}

        }

然后,如果您尝试示例化或扩展此类,则应该得到一个编译时错误。

相关问题