javascriptecmascript-6

Js using reflection to create subclass in parentclass method


I got this idea about js extends system. It'll be much easier to understand what i mean by reading the following codes

in moduleA.js I have Frame class

class Frame{  // contains frame info 

    static Predefined_Paramters_Pattern = [1,2,3,4]

    constructor(someParameters = {variable1=...,variable2=...,tag = 0}){
      //do something
      this.someParamtersPattern = someParamters
    }

    nextFrame(){
      // for example
      // when i call nextFrame it 'll construct 4 subclasses 
      // base on [this] constructor paramaters
      // constructorParmatersPattern = {variable1=...,variable2=...,tag= 1 or 2 or 3 or 4}
      // this code may looks meaningless 
      // but i just wanna make this a lot easier to be comprehended what i mean 
      // and avoid stucking into a complex business logic
      Frame.Predefined_Paramters_Pattern.forEach(e=>{
          // create sub class somehow
          let type = this.type
          this.someParamtersPattern.tag = e
          let constructorParmatersPattern = this.someParamtersPattern
          // if i use eval(`new ${type}(${constructorParmatersPattern })`)
          // the browser will throw a error looks like 'SubFrame1 is not define'
      })
      
    }
 }
export {Frame}

in moduleB.js I have SubFrame1 class

import {Frame} from './moduleA.js'

class SubFrame1 extends Frame{
    constructor(somePramaters){
      //do something
      super(somePramaters)
      //do something
      this.type = 'SubFrame1'
    }

}
export {SubFrame1}

Now what I want to achieve is when i call new SubFrame1().nextFrame(), it'll create several SubFrames automaticlly which are similar to the one I created. I can define some patterns for their constructor's paramaters. So no matter how many subclasses i have, as long as they extends Frame, then they all share the same patterns when they call .nextFrame().

But the thing is I do not wish to have a SubFrame1 class or SubFrame1,SubFrame2,...,SubFrame3 classes 's reference in my original class.

like this one

import {SubFrame1} from './subframe1.js'
import {SubFrame2} from './subframe2.js'
......
import {SubFrameN} from './subframen.js'

class Frame{
  ......
}

i'm pretty much a rookie to javascript but at school i was tought and told to write codes so I can reuse them and reduce redundant codes, any help or corrections would be great


Solution

  • So you want new SubFrame1().nextFrame() to construct a SubFrame1 instance, but new SubFrame2().nextFrame() to construct a SubFrame2 instance. Nothing easier than that, you don't even need a type property for that! JS prototype object (e.g. built with class syntax) already do contain a .constructor property holding the constructor function that you can call to create a new instance of the same (sub)class.

    export class Frame{  // contains frame info
        constructor(someParameters) {
            // do something
            this.someProperties = someParameters;
        }
    
        nextFrame() {
            const type = this.constructor;
            const instance = new type(this.someProperties);
            return instance;
        }
    }
    

    Now this assumes that the subclass constructors would be called with the same signature, and always expect the this.someProperties object as arguments for the cloning of the frame. To customise this, the subclass could of course modify this.someProperties, but as soon as the signatures become too different the subclass should better override the whole method:

    class SpecialFrame extends Frame {
        constructor(someParameters, someSpecials) {
            super(someParameters);
            this.specialProperties = someSpecials;
        }
        nextFrame() {
            return new this.constructor(this.someProperties, this.specialProperties);
        }
    }
    

    This can also be used for more complex initialisation than just copying a property value, or for hardcoding some specific arguments that nextFrame should always use. If nextFrame does more than just the cloning, split it into two methods - clone() that creates the copy and may be overridden in the subclasses, and nextFrame that calls this.clone() then modifies the copy to become the next frame instead of the same.