1

Let's say that we have the following code...

class Person {
    sayHello() {
        console.log('hello');
    }

    walk() {
        console.log('I am walking!');
    }
}

class Student extends Person {
    sayGoodBye() {
        console.log('goodBye');
    }

    sayHello() {
        console.log('hi, I am a student');
    }
}

var student1 = new Student();
student1.sayHello();
student1.walk();
student1.sayGoodBye();

// check inheritance
console.log(student1 instanceof Person); // true
console.log(student1 instanceof Student); // true

That works well... but now let's say that the Student class doesn't extend Person at it's declaration class Student extends Person { becomes class Student {.

Now we have class Person and class Student.

Is there a way to have Student extend Person without having the extends in the class declaration?

EDIT: [more detail]

The reason I'm using this pattern is because I'd like to use Mongoose's extends Model but I'm creating the Model objects in a node_module rather than in the back-end API. This is so that I can use shared classes for the front and back-end reducing redundant code. I obviously can't use mongoose in the front-end so I'm only going to be extending that functionality in the back-end.

jscul
  • 748
  • 1
  • 10
  • 25
  • Possible duplicate of [Extending an Object in Javascript](https://stackoverflow.com/questions/10430279/extending-an-object-in-javascript) – Matthias Jul 23 '19 at 22:10
  • 3
    What is the purpose of not extending the base class in the declaration? Can you explain why you're compelled to do this in the first place? – Patrick Roberts Jul 23 '19 at 22:13
  • @PatrickRoberts I was looking to use the class as a mongoose Model without having to use extends model... but I think this works -> `schema.loadClass(Person);` [here](https://mongoosejs.com/docs/advanced_schemas.html) – jscul Jul 23 '19 at 22:29

1 Answers1

1

It is impossible to do with class, because for a "class" to extend another class, it's prototype must be an instance of the other class, and when you use the class keyword, the prototype attribute is not configurable:

console.log(Object.getOwnPropertyDescriptor((class {}), 'prototype'));

If you were to use function classes instead, you can use this to change the parent class.

const change_parent = (clazz, new_parent) => {
    clazz.prototype = Object.assign(Object.create(new_parent.prototype), clazz.prototype);
};

Otherwise, you have to create a new class to have a different parent class.

const with_new_parent = (clazz, new_parent) => {
    class C extends new_parent {};
    Object.assign(C.prototype, clazz.prototype);
    return C;
};

Usage:

const change_parent = (clazz, new_parent) => {
    clazz.prototype = Object.assign(Object.create(new_parent.prototype), clazz.prototype);
};

class Person {
    sayHello() {
        console.log('hello');
    }

    walk() {
        console.log('I am walking!');
    }
}

function Student() {}

Student.prototype = {
    constructor: Student,
    sayGoodBye() {
        console.log('goodBye');
    },
    sayHello() {
        console.log('hi, I am a student');
    }
};

var student1 = new Student();
student1.sayHello();
console.log('student1 has walk:', 'walk' in student1);  // false; not a Person
student1.sayGoodBye();

// check inheritance
console.log('student1 instanceof Person:', student1 instanceof Person); // false
console.log('student1 instanceof Student:', student1 instanceof Student); // true

change_parent(Student, Person);

student1 = new Student();
student1.sayHello();
console.log('student1 has walk:', 'walk' in student1);  // true; now a Person
student1.walk();
student1.sayGoodBye();

// check inheritance
console.log('student1 instanceof Person:', student1 instanceof Person); // true
console.log('student1 instanceof Student:', student1 instanceof Student); // true

After seeing your edit, it would be much easier to achieve what you want like this:

class MyModel extends (is_nodejs ? Model : Object) {
    // ...
};
Artyer
  • 31,034
  • 3
  • 47
  • 75
  • This would be the answer to the question... turns out Mongoose has a function where you can set the Model class using like `schema.loadClass(Person);`... this works perfectly! Thank you so much for your help. – jscul Jul 23 '19 at 22:52