简体   繁体   中英

JavaScript - Class extend on condition

Here is the thing. I have a main class called A. I want this class to extend class B.

class A extends B {}

But in fact, I want the class B to extend C, D or E on a specific condition:

class B extends B1 {}

or

class B extends B2 {}

or

class B extends B3 {}

So the B class would be a "fake" class, just to check a condition and then extend the right class. In the final, the result would be the same as:

class A extends B1 {}

or

class A extends B2 {}

or

class A extends B3 {}

I know this is possible in PHP, with abstract classes or wrapper classes for example. But how to do that in JavaScript ES6?

Thanks

Weird, but possible:

 class subClassFirst { report() { console.log(`Extended ${this.name} from the first class`); } } class subClassSecond { report() { console.log(`Extended ${this.name} from the second class`); } } class subClassThird { report() { console.log(`Extended ${this.name} from the third class`); } } function classCreator(condition) { let sub; switch (condition) { case 'first': sub = subClassFirst; break; case 'second': sub = subClassSecond; break; case 'third': sub = subClassThird; break; } return (class extends sub { constructor(name) { super(); this.name = name; } }); } let myClass; myClass = classCreator('first'); let mcf = new myClass('f'); myClass = classCreator('second'); let mcs = new myClass('s'); myClass = classCreator('third'); let mct = new myClass('t'); mcf.report(); mcs.report(); mct.report();

I found blog post that gave an easy es6 way that doesn't use util.inherits https://www.mikedoesweb.com/2017/dynamic-super-classes-extends-in-es6/

Here is how I used a passed option to determine which class to extend and then obfuscated that in the export

import ClassB from '  '
import ClassA from '  '

const ext = {
   classA: ClassA, // the default
   classB: ClassB
// can do as many as you want
}


function ExtendsMyClass (opts= {}) {

  if (!new.target) {
    throw new Error('Uncaught TypeError: Class constructor Interrupt cannot be invoked without \'new\'')
  }

// one could vet opts here too including opts.extend

   class MyClass extends ext[opts.extend || 'classA'] {
    constructor(opts = {}) {
      super(opts)
   ....
    }
} // end MyClass

return new MyClass(opts)

} // end dynamic extend

export default ExtendsMyClass
export { ExtendsMyClass as MyClass }

I'll probably make this into "wrapper" utility function that accepts also the child class as well. That way one can dynamically extend any class as opposed to the one off implementation above. Could even implement dynamic imports if it was set up an async function.

So classes in javascript are really not setup in the same classical inheritance way as other languages, the best way to do what you want is to set the prototype of the object you are dealing with. There are a few ways.

Object.setPrototypeOf(currentObj, newPrototype);

Where newPrototype is the object you are wanting to inherit from. Here are a couple good articles on it if you want to learn the inner workings.

http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/

https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch5.md

There's a Node JS function for that

const util = require("util");

class MySubClass {}
class MySuperClass {}

util.inherits(MySubClass, MySuperClass);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM