admin管理员组文章数量:1355535
Imagine I have 3 classes Child
, Parent
and Grandparent
connected in hierarchy as follows:
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?
}
}
How can I call Grandparent
's setter of myField
in setter of Child
class?
I'm interested particularly in setter, not a method. Also it's much preferable to not make changes in Parent
of Grandparent
classes.
I don't see how that is possible using super
because it references just Parent
class, as well as using something like Grandparent.prototype.<what?>.call(this, ...)
because I don't know what exactly to call in the prototype.
Does anyone have any suggestions for this case?
Thanks in advance!
Imagine I have 3 classes Child
, Parent
and Grandparent
connected in hierarchy as follows:
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?
}
}
How can I call Grandparent
's setter of myField
in setter of Child
class?
I'm interested particularly in setter, not a method. Also it's much preferable to not make changes in Parent
of Grandparent
classes.
I don't see how that is possible using super
because it references just Parent
class, as well as using something like Grandparent.prototype.<what?>.call(this, ...)
because I don't know what exactly to call in the prototype.
Does anyone have any suggestions for this case?
Thanks in advance!
Share Improve this question edited Mar 18, 2019 at 23:49 Alena Levina asked Mar 18, 2019 at 19:26 Alena LevinaAlena Levina 1332 silver badges8 bronze badges 4- 1 without a distinct ref to it, you can't call it. – dandavis Commented Mar 18, 2019 at 19:31
- 1 Possible duplicate of How can I call my class' parent's parent's constructor in ES6? – Get Off My Lawn Commented Mar 18, 2019 at 19:32
- stackoverflow./questions/36370790/… – Get Off My Lawn Commented Mar 18, 2019 at 19:32
- @GetOffMyLawn thanks for ideas, but my questions is particularly about setter, there is a specific for it which differs it from how same can be acplished for method – Alena Levina Commented Mar 18, 2019 at 23:51
4 Answers
Reset to default 8using something like
Grandparent.prototype.<what?>.call(this, ...)
You're on the right track there, you can access the setter method using Object.getOwnPropertyDescriptor
:
Object.getOwnPropertyDescriptor(Grandparent.prototype, "myField").set.call(this, value);
There is a much easier way though: using the Reflect.set
helper with a custom receiver:
Reflect.set(Grandparent.prototype, "myField", value, this);
This also has the advantage that it still works when Grandparent
doesn't define a setter.
That said, I agree with @Dinu that there's probably a problem with your class hierarchy (or your general design, maybe you shouldn't even use classes or inheritance) when you need to do this.
You can use Reflect.set()
with the optional receiver
argument like this:
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';
If you don't have an explicit reference to Grandparent.prototype
, you can use Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(this)))
instead which is obviously a lot less preferable. You could create a helper function though:
function getPrototypeOf (target, level = 1) {
return level > 0 ? getPrototypeOf(Object.getPrototypeOf(target), level - 1) : target;
}
and use getPrototypeOf(this, 3)
in place of Grandparent.prototype
to recurse up the prototype chain to the grandparent:
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';
You might find a way to do it, but you shouldn't, not while you're doing class-based OOP, because it breaks the class-based model. In any sane environment, if Parent implements setX(), it expects that setX() behaves the way it defined it, in its context. It does not override setX() so that it can behave the way it did before.
So, if you're asking this, you either designed your class hierarchy wrong, or you actually need the prototype-based OOP.
If you write Parent, I assume what you are trying to obtain is an unmediated access to a certain property. The way to go is to define a method on parent/gradpa, like setXClean(), that is used as a celan setter. In this context, you probably want it to be protected and final on the grandparent.
The easiest way in my opinion, would be to just create another unique setter or method in the Grandparent class that sets myField
.
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
}
}
Another option would be to put super.myField
in each setters body:
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
}
}
本文标签: ecmascript 6How to call setter of grandparent class in JavascriptStack Overflow
版权声明:本文标题:ecmascript 6 - How to call setter of grandparent class in Javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743957715a2568436.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论