Search code examples
javascriptnode.jstypescriptoopinheritance

Creating instance of child class in parent method


I have something similar to the following code for a parent and child class:

const modify = (data) => {
  const newData = data
  // changes newData in some way
  return newData
}

class Parent {
  constructor(data) {
    this.data = data
  }

  modify() {
    return new Parent(modify(this.data))
  }
}

class Child extends parent {
  constructor(data) {
    super(data)
  }
}

Is there a way to change the Parent class's modify function to return an instance of Child when it is called using an instance of Child?

I know that in a static function, you can use new this() to do that, is there something equivalent for methods? Or would I have to overwrite the Parent method in the Child class?


Solution

  • I would just compose the method call for the Parent and the Child to ensure that the proper instance is created.

    Since the modify function is doing all the work, it's not that hard to just define a modify on both the Parent and the Child.

    const main = () => {
      console.log('=== Parent ===');
      let parent = new Parent({ timestamp: Date.now() });
      console.log(parent);
      parent = parent.modify({ timestamp: Date.now(), updated: true });
      console.log(parent);
      console.log(parent.constructor.name); // Parent
      
      console.log('=== Child ===');
      let child = new Child({ timestamp: Date.now() });
      console.log(child);
      child = child.modify({ timestamp: Date.now(), updated: true });
      console.log(child);
      console.log(child.constructor.name); // Child
    };
    
    // Naive merge function
    const modify = (source, update) => ({ ...source, ...update });
    
    class Parent {
      constructor(data) {
        this.data = data
      }
      modify(update) {
        return new Parent(modify(this.data, update));
      }
    }
    
    class Child extends Parent {
      constructor(data) {
        super(data)
      }
      modify(update) {
        return new Child(modify(this.data, update));
      }
    }
    
    main();
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    If you really want to define the modify method for only the Parent and inherit it for the Child, you try the following.

    class Parent {
      constructor(data) {
        this.data = data
      }
      modify(update) {
        return new this.constructor(modify(this.data, update));
      }
    }
    
    class Child extends Parent {
      constructor(data) {
        super(data)
      }
    }