CherryNerd
CherryNerd

Reputation: 1314

Static function inheritance

I've created a few classes as Controllers for my routes in Node.js and I'd like them to be able to work on a singleton basis (not required, it's an extra)

Main Controller class

class RouteController {

    static getInstance() {
        if (!RouteController.singleton) {
            RouteController.singleton = new RouteController();
        }

        return RouteController.singleton;
    }
}

Now I want to create a route for example viewing posts and I want that class to have the singleton pattern as well, but not cop

PostController class

class PostController extends RouteController {

}

If I do this and check it console.log(RouteController.getInstance() === PostController.getInstance()) it returns true when I want each (sub)class to have their own singleton instance.

How can I do this correctly?

Upvotes: 0

Views: 45

Answers (2)

Felix Kling
Felix Kling

Reputation: 816364

The normal rules of functions apply. Hence you can use this inside the function to refer to the object the method was invoked on (the constructor function itself in this case):

class RouteController {

    static getInstance() {
        if (!this.singleton) {
            this.singleton = new this();
        }

        return this.singleton;
    }
}

However, this will still not work if RouteController.getInstance() is called directly, because then all subclasses inherit a static singleton property, causing the !this.singleton test to fail for each subclass.

There are multiple ways to solve this. One would be to use getOwnProperty instead of accessing it directly:

if (!this.getOwnProperty('singleton')) {

}

Upvotes: 0

Mike Cluck
Mike Cluck

Reputation: 32511

One simple way would be to see if your singleton property is an instance of this. This will work even if you call RouteController.getInstance() before doing so on any of the derived classes.

class RouteController {
  log() {
    return 'Route';
  }
  static getInstance() {
    if (!(this.singleton instanceof this)) {
      // Only called twice so you can verify it's only initialized
      // once for each class
      console.log('Creating singleton...');
      this.singleton = new this();
    }
    return this.singleton;
  }
}

class PostController extends RouteController {
  log() {
    return 'Post';
  }
}

console.log(RouteController.getInstance().log());
console.log(PostController.getInstance().log());
console.log(RouteController.getInstance().log());
console.log(PostController.getInstance().log());

Upvotes: 2

Related Questions