英文:
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) => 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 -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论