扩展单例类,使用私有属性

huangapple go评论88阅读模式
英文:

Extending singleton class with private properties

问题

  1. 我有一个单例类,我想扩展它。不扩展这个类的话没问题,但如果我使用扩展的版本,会出现“无法在同一对象上两次初始化#b”的错误。

class A {
static #instance = null
#a = 1
constructor() {
if (!A.#instance) {
A.#instance = this
}
return A.#instance
}
}

class B extends A {
#b = 2
}

  1. `[new A(), new A()]` 可行
  2. `[new B(), new B()]` 抛出错误。
英文:

I have a singleton class that I want to extend. Without extending the class it's fine but get
Uncaught TypeError: Cannot initialize #b twice on the same object if I use the extended version.

  1. class A{
  2. static #instance = null
  3. #a = 1
  4. constructor(){
  5. if(!A.#instance){
  6. A.#instance = this
  7. }
  8. return A.#instance
  9. }
  10. }
  11. class B extends A{
  12. #b = 2
  13. }

[new A(),new A()] works

[new B(),new B()] throws an error.

答案1

得分: 0

你的A::constructor()中存在一个缺陷:
从构造函数中返回了A类的第一个创建的实例,保存在静态属性中,因此将其重用作类B的所有实例的父实例。
因此,你尝试两次初始化相同的#b,会引发错误。

要实现单例设计模式,你可以代理这些类(幸运的是我们可以代理JS类!):

  1. const proxify = (what) => new Proxy(what, {
  2. instance: null,
  3. construct(B, args) {
  4. return this.instance ??= new what(...args);
  5. }
  6. });
  7. const A = proxify(class {
  8. #a = 1
  9. c = 0
  10. });
  11. const B = proxify(class extends A {
  12. #b = 2
  13. d = 0
  14. });
  15. // 确保我们有一个A的单例
  16. const a1 = new A;
  17. const a2 = new A;
  18. a2.c = 1;
  19. console.log(a1.c, a2.c);
  20. // 确保我们有一个B的单例
  21. const b1 = new B;
  22. const b2 = new B;
  23. b1.c = 2;
  24. b2.d = 3;
  25. console.log(b1.c, b2.c);
  26. console.log(b1.d, b2.d);

(注意:这是代码的翻译部分,不包括问题的回答。)

英文:

You have a flaw in your A::constructor():
From the constructor you return the first created instance of A saved in a static property thus reusing it as a parent instance of all instances of the class B.
Thus you try to initialize the same #b twice which throws.

To implement your singleton design pattern you could proxify the classes (luckily we can proxify a JS class!):

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

  1. const proxify = (what) =&gt; new Proxy(what, {
  2. instance: null,
  3. construct(B, args) {
  4. return this.instance ??= new what(...args);
  5. }
  6. });
  7. const A = proxify(class {
  8. #a = 1
  9. c = 0
  10. });
  11. const B = proxify(class extends A {
  12. #b = 2
  13. d = 0
  14. });
  15. // make sure we have a singleton for A
  16. const a1 = new A;
  17. const a2 = new A;
  18. a2.c = 1;
  19. console.log(a1.c, a2.c);
  20. // make sure we have a singleton for B
  21. const b1 = new B;
  22. const b2 = new B;
  23. b1.c = 2;
  24. b2.d = 3;
  25. console.log(b1.c, b2.c);
  26. console.log(b1.d, b2.d);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月9日 03:10:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76435014.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定