想象一下,我有3个类Child
,Parent
和Grandparent
在层次结构中进行了如下连接:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
//I know how to call Parent's setter of myField:
//super.myField = value;
//But how to call Grandparent's setter of myField here?
}
}
如何在Grandparent
类的设置器中调用myField
的{{1}}的设置器?
我特别对二传手而不是方法感兴趣。同样,最好不要在Child
类的Parent
中进行更改。
我不知道使用Grandparent
是怎么回事,因为它仅引用super
类,也无法使用Parent
之类的东西,因为我不知道确切地调用什么在原型中。
有人对此案有任何建议吗?
谢谢!
答案 0 :(得分:7)
使用类似
Grandparent.prototype.<what?>.call(this, ...)
您在正确的轨道上,可以使用Object.getOwnPropertyDescriptor
访问setter方法:
Object.getOwnPropertyDescriptor(Grandparent.prototype, "myField").set.call(this, value);
不过,有一种更简单的方法:将Reflect.set
helper与自定义接收者一起使用:
Reflect.set(Grandparent.prototype, "myField", value, this);
这还有一个优势,当Grandparent
未定义设置器时,它仍然可以工作。
也就是说,我同意@Dinu的观点,当您需要这样做时,您的类层次结构(或您的一般设计,也许甚至不应该使用类或继承)可能存在问题。
答案 1 :(得分:2)
您可以将Reflect.set()
与可选的receiver
参数一起使用:
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(Grandparent.prototype, 'myField', value, this);
}
}
new Child().myField = 'foo';
如果您没有明确引用Grandparent.prototype
,则可以使用Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(this)))
代替,这显然不那么可取。不过,您可以创建一个辅助函数:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
并使用getPrototypeOf(this, 3)
代替Grandparent.prototype
将原型链递归给祖父母:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
Reflect.set(getPrototypeOf(this, 3), 'myField', value, this);
}
}
new Child().myField = 'foo';
答案 2 :(得分:1)
您可能会找到一种实现方法,但不应该这样做,因为在使用基于类的OOP时,这样做会破坏基于类的模型。在任何理智的环境中,如果Parent实现setX(),则它希望setX()在其上下文中表现其定义方式。它不会覆盖setX(),因此它可以像以前一样运行。
因此,如果您要问这个问题,那么您要么设计了错误的类层次结构,要么实际上需要基于原型的OOP。
如果您写《父母》,我假设您要获取的是对特定属性的无中介访问。方法是在父/ gradpa上定义一个方法,例如setXClean(),该方法用作celan setter。在这种情况下,您可能希望对其进行保护,并在祖父母身处将其定案。
答案 3 :(得分:0)
在我看来,最简单的方法是在创建myField
的Grandparent类中创建另一个唯一的setter或方法。
class Grandparent {
set myField(value) {
console.log('Grandparent setter');
}
set grandParent_myField(value) { this.myField = value }
}
class Parent extends Grandparent {
set myField(value) {
console.log('Parent setter');
}
}
class Child extends Parent {
set myField(value) {
this.grandParent_myField = value
}
}
另一种选择是将super.myField
放在每个设置者的正文中:
class Grandparent {
constructor() { this._myField = null }
set myField(value) {
this._myField = value
}
}
class Parent extends Grandparent {
set myField(value) {
super.myField = value
}
}
class Child extends Parent {
set myField(value) {
super.myField = value
}
}