内置 类 的 sub类 的私有字段是否无法在重写方法中访问?
Are private fields of subclasses of built-in classes not accesible inside overriden methods?
我有以下扩展内置数据类型集的 class。它通过检查要添加到集合中的每个元素是否符合指定为构造函数的第一个参数的类型来添加一些额外的功能。它通过 typeof
运算符进行这种愚蠢的“类型检查”。我将 Set 的类型保存在私有字段中。如果我尝试重写 .add()
方法以便它也进行这种类型检查,我会收到一条错误消息 Uncaught TypeError: can't access private field or method: object is not the right class
class TypedSet extends Set {
#type;
constructor(type, elements) {
if (elements && !elements.every(e => typeof e === type)) throw new TypeError(`Not all elements conform to type t->${type}`)
super(elements)
this.#type = type
}
add(e) {
return typeof e === this.#type
? super.add(e)
: new TypeError(`Type of element e does not conform to type t: ${this.#type}`)
}
}
const s = new TypedSet('string', ['hello', 'world'])
s.add('!')
如果我尝试在覆盖的 .add()
方法中访问私有字段(我在 subclass 中声明的字段),为什么会出现该错误?如果我将 .add()
方法重命名为类似 .typeAdd()
的方法,引用私有字段不会引发错误
问题是super(elements)
会调用add
方法将元素添加到集合1。那时,您的子类构造函数尚未创建字段 (this.#type = type
).
作为解决方法,您可以使用
class TypedSet extends Set {
#type;
constructor(type, elements) {
super()
this.#type = type
for (const e of elements ?? []) {
if (typeof e !== type) throw new TypeError(`Not all elements conform to type t->${type}`)
super.add(e) // or this.add(e)
}
}
add(e) {
return typeof e === this.#type
? super.add(e)
: new TypeError(`Type of element e does not conform to type t: ${this.#type}`)
}
}
const s = new TypedSet('string', ['hello', 'world'])
s.add('!')
1:从构造函数调用可重写的方法通常被认为是一种反模式,正是因为您的用例不起作用。不知道为什么 ECMAScript 确实指定了这一点。另一方面,也不推荐 - 即使可能 - 扩展内置 类,这样的惊喜太多了。组合通常是更好的方法。
我有以下扩展内置数据类型集的 class。它通过检查要添加到集合中的每个元素是否符合指定为构造函数的第一个参数的类型来添加一些额外的功能。它通过 typeof
运算符进行这种愚蠢的“类型检查”。我将 Set 的类型保存在私有字段中。如果我尝试重写 .add()
方法以便它也进行这种类型检查,我会收到一条错误消息 Uncaught TypeError: can't access private field or method: object is not the right class
class TypedSet extends Set {
#type;
constructor(type, elements) {
if (elements && !elements.every(e => typeof e === type)) throw new TypeError(`Not all elements conform to type t->${type}`)
super(elements)
this.#type = type
}
add(e) {
return typeof e === this.#type
? super.add(e)
: new TypeError(`Type of element e does not conform to type t: ${this.#type}`)
}
}
const s = new TypedSet('string', ['hello', 'world'])
s.add('!')
如果我尝试在覆盖的 .add()
方法中访问私有字段(我在 subclass 中声明的字段),为什么会出现该错误?如果我将 .add()
方法重命名为类似 .typeAdd()
的方法,引用私有字段不会引发错误
问题是super(elements)
会调用add
方法将元素添加到集合1。那时,您的子类构造函数尚未创建字段 (this.#type = type
).
作为解决方法,您可以使用
class TypedSet extends Set {
#type;
constructor(type, elements) {
super()
this.#type = type
for (const e of elements ?? []) {
if (typeof e !== type) throw new TypeError(`Not all elements conform to type t->${type}`)
super.add(e) // or this.add(e)
}
}
add(e) {
return typeof e === this.#type
? super.add(e)
: new TypeError(`Type of element e does not conform to type t: ${this.#type}`)
}
}
const s = new TypedSet('string', ['hello', 'world'])
s.add('!')
1:从构造函数调用可重写的方法通常被认为是一种反模式,正是因为您的用例不起作用。不知道为什么 ECMAScript 确实指定了这一点。另一方面,也不推荐 - 即使可能 - 扩展内置 类,这样的惊喜太多了。组合通常是更好的方法。