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

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

Extending singleton class with private properties

问题

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

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

class B extends A {
#b = 2
}


`[new A(), new A()]` 可行

`[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.

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

class B extends A{
    #b = 2
}

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

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

答案1

得分: 0

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

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

const proxify = (what) => new Proxy(what, {
    instance: null,
    construct(B, args) {
        return this.instance ??= new what(...args);
    }
});

const A = proxify(class {
    #a = 1
    c = 0
});

const B = proxify(class extends A {
    #b = 2
    d = 0
});

// 确保我们有一个A的单例

const a1 = new A;
const a2 = new A;
a2.c = 1;

console.log(a1.c, a2.c);

// 确保我们有一个B的单例

const b1 = new B;
const b2 = new B;
b1.c = 2;
b2.d = 3;

console.log(b1.c, b2.c);
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 -->

const proxify = (what) =&gt; new Proxy(what, {
    instance: null,
    construct(B, args) {
        return this.instance ??= new what(...args);
    }
});

const A = proxify(class {
    #a = 1
    c = 0
});

const B = proxify(class extends A {
    #b = 2
    d = 0
});

// make sure we have a singleton for A

const a1 = new A;
const a2 = new A;
a2.c = 1;

console.log(a1.c, a2.c);

// make sure we have a singleton for B

const b1 = new B;
const b2 = new B;
b1.c = 2;
b2.d = 3;

console.log(b1.c, b2.c);
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:

确定