Home > Software engineering >  Calling constructor of parent class in static method of child class
Calling constructor of parent class in static method of child class

Time:02-11

I got a problem with calling super inside of the child static method.

const _todos = [];

class Todo {
  constructor(title) {
    this.title = title;
    this.id = Math.round(Math.random() * 100);
    _todos.push({title, id: this.id});

    console.log(`Todo ID: ${this.id}. DONT FORGET IT!`);
  }

  static TodoerVersion = '1.8';

  static removeTodo(id) {
    const todoIndex = _todos.findIndex(t => t.id == id);
    _todos.splice(todoIndex, 1);
  }
}

class TodoV2 extends Todo {
  static addTodo(title) {
    super(title);
  }

  static addDescription(todo, description) {
    todo.description = description;
  }

  static TodoerVersion = '2.0';
};

new TodoV2("play guitar");

Why does it not work? But if i call super in normal method, it would works just fine.

CodePudding user response:

super is only callable within the constructor function of a class.

Two answers for you:

  1. The question you actually asked.

  2. What I think you should do instead. :-)

Answering the question you asked:

JavaScript is very special in this regard: this has meaning in static methods (as long as you call them correctly, e.g. TodoV2.addTodo("title")): it's the constructor function you called the static method on. And a subclass constructor function inherits from its superclass constructor function (yes, really). So you can access the constructor function for the parent class using Object.getPrototypeOf(this) in the static method:

// This is something unusual that JavaScript actually does support
static addTodo(title) {
    const ctor = Object.getPrototypeOf(this);
    return new ctor(title);
}

To handle the case where the user may have called addTodo in a way that doesn't set this, you might do something like this to default to TodoV2 if this is undefined:

static addTodo(title) {
    const ctor = Object.getPrototypeOf(this ?? TodoV2);
    return new ctor(title);
}

What I think you should do instead

You shouldn't be using a static method for this. Instead, define a constructor for TodoV2:

class TodoV2 extends Todo {
    constructor(title, description) {
        super(title);
        this.description = description ?? "";
    }

    static addTodo(title) { // Why no `description`?
        return new this(title); // Or `new TodoV2(title)`
    }
}

You might also look into the Symbol.species pattern if you want subclasses to create instances of superclasses.

  • Related