1

I need to change a Parent's static method from a subclass.

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static I read:

Static method calls are made directly on the class and are not callable on instances of the class.

In the example below, I have a Parent class with a foo() method which calls the bar() method (both static). I would need to change bar from Child subclass so that calling Child.foo() will call the modified bar method and not the original one.

Is there a possibility (maybe something in the Child's constructor)?

class Parent {

  static foo() {
    Parent.bar();
  }

  static bar() {
    console.log("HERE I AM");
  }

}

class Child extends Parent {

  static bar() {
    super.bar(); // maybe not what I want?
    console.log(", FELLAS!");
  }
}

Parent.foo(); // HERE I AM
Child.foo(); // HERE I AM, FELLAS! (need this!)
umbe1987
  • 2,894
  • 6
  • 35
  • 63
  • well, that's the problem, I would need to call `Child.foo()` instead, and banging my head on how to make it work... Will add this info in the question. – umbe1987 Jul 28 '19 at 21:31
  • 1
    Why have `foo()` at all? Calling `bar()` instead gives you the behavior you want. `Parent.bar()` outputs "HERE I AM", Child.bar() outputs "HERE I AM\n, FELLAS!". – Tibrogargan Jul 28 '19 at 21:35
  • @Tibrogargan I am trying to implement a method (`RenderLayer_()`) implemented in [the code of another person](https://github.com/walkermatt/ol-layerswitcher/blob/a9d983c0e8e6286cf32779cc690ff1773f0d9bb5/src/ol-layerswitcher.js#L277) and called from another (more than one) methods. – umbe1987 Jul 28 '19 at 21:38
  • @Paulpro I tried to explain why in my previous comment. I am just wondering if this is feasible somehow. The reason why I am trying this is not so simple, but it's mainly because I would like an easy way to extending a static method of a class which has to be called by another method of the same class. – umbe1987 Jul 28 '19 at 21:43
  • Don't get the downvotes... I think the problem is kind of clear. If it is not feasible I would prefer someone who tell me so, rather than silent downvotes without any justification. – umbe1987 Jul 28 '19 at 21:45
  • Have a look at [this](https://stackoverflow.com/questions/28627908/call-static-methods-from-regular-es6-class-methods) – Bergi Jul 28 '19 at 21:54
  • @umbe1987 you don't have any downvotes. no upvotes either – Tibrogargan Jul 28 '19 at 22:02
  • @Tibrogargan I had when I wrote the comment. Anyway, could also be an accidental downvote, Idon't have the reputation to see it. – umbe1987 Jul 28 '19 at 22:06
  • You could have avoided referring to a Parent/Child relationship. It's not necessary for what you're trying to achieve (replace a static function in another class). Using Parent/Child kind of muddies the waters. – Tibrogargan Jul 28 '19 at 22:53
  • Frankly, your ask is just wrong. A static method is not attached to any instance, so having a child override or replace the parent's static would affect ALL calls to that parent's static method from anywhere. It's equivalent to replacing a function with a different function. Everyone who calls the function is affected. So, the real question here should be how to fix your design so that what you're asking for is not required. You need a better way to solve whatever your design problem is without doing this. – jfriend00 Jul 28 '19 at 23:38
  • @jfriend00 Probably. The point is: the Parent class is not owned by me. I have a project which aims to use some functionality of it, whike others should be extended (not changed). Mine was a question to understand whether this would have been a viable solution, but I am open to think it's not or at least to change my plans in light of what I just discovered thanks to these comments and answers. Also, I wuold just need the Child class in my project, as an extended version of the Parent. – umbe1987 Jul 29 '19 at 07:02

2 Answers2

2

Your problem is that foo directly calls Parent.bar(), not this.bar(). By explicitly referring to Parent, it doesn't consider the overwritten method in Child at all. It doesn't matter how Child.bar is written and whether it calls super.bar or not.

class Parent {
  static foo() {
    this.bar();
//  ^^^^
  }
  static bar() {
    return "HERE I AM";
  }
}

class Child extends Parent {
  static bar() {
    return super.bar() + ", FELLAS!";
  }
}

console.log(Parent.foo()); // HERE I AM
console.log(Child.foo()); // HERE I AM, FELLAS!

The this keyword in the static bar() method now refers to the Child class in the Child.foo() call, and calls its overridden bar method.

The only alternative (if you cannot modify Parent) would be to overwrite the foo method as well, duplicating the Parent code but calling Child.bar() explicitly there.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

If you want to modify the Parent from the child just do it. Parent is an object with properties, static is syntactic sugar. Replacing a method is a simple as setting a property. Probably not something you want to do in production code.

class Parent {
  static foo() {
    Parent.bar();
  }

  static bar() {
    console.log("HERE I AM");
  }
}

class Child extends Parent {
  static unhack() {
      if (Parent.hack) {
          Parent.bar = Parent.hack
          delete Parent.hack
      }
  }
  
  static hack() {
    if (!Parent.hack) {
       Parent.hack = Parent.bar
       Parent.bar = Child.bar
    }
  }
 
  static foo() {
      Child.hack()
      Parent.foo()
      Child.unhack()
  }

  static bar() {
    if (super.hack) {
      super.hack(); // Call the "shadowed" Parent.bar()
    }
    console.log(", FELLAS!"); // Call the additional code
  }
}

Parent.foo(); // HERE I AM
Child.foo(); // HERE I AM, FELLAS! (need this!)
Parent.bar(); // HERE I AM
Child.bar(); // Probably don't want to do this
Tibrogargan
  • 4,508
  • 3
  • 19
  • 38
  • Seems what I need! Will come back to you tomorrow when I can test it. Thanks and sorry not to make it now... – umbe1987 Jul 28 '19 at 22:09
  • Yeah, that did the trick, although I think I might follow another route as per the many (and yours) comments. Thanks! – umbe1987 Jul 29 '19 at 07:30
  • Why do this complicated stuff with `hack` and `unhack` at all? Just don't call into `Parent.foo()` from `Child.foo()` and you won't have any problems. – Bergi Jul 29 '19 at 10:05
  • @bergi might have been jumping to conclusions about what exactly the OP was doing, but yes, on the face of it `Parent.foo(); Child.bar()` achieves the same result without all the messing around. – Tibrogargan Jul 30 '19 at 04:06