For example, using mix-ins to extends multiple utility classes, like this:
import { autorun, makeObservable } from "mobx";
type GConstructor<T = {}> = new (...args: any[]) => T;
interface HasLife {
grow: () => void;
}
class Animal {
age: number;
constructor(age: number) {
this.age = age;
}
}
function addLife<TBase extends GConstructor<Animal>>(Base: TBase) {
return class Jumpable extends Base {
// this is wrong, mixins class cannot use constructor!
constructor() {
super();
makeObservable(this, {
age: observable,
grow: action,
});
}
grow() {
this.age++;
}
};
}
class Dog extends addLife(Animal) implements HasLife {
constructor(age: number) {
super(age);
}
}
const dog = new Dog(0);
autorun(() => {
console.log(dog.age);
});
dog.grow();
The example I provided cannot run correctly because mixin classes cannot have constructors, but I would also like to mark the member methods as observable or action in the mixin classes.
What should I do?
or, What is the common approach within the mobx community for dealing with this problem using other methods?
What is the difference between :
class myclassA {
methodA() {console.log('I\'m a the class A method'); }
}
class myclassB {
classA = new myclassA;
methodB() {this.classA.methodA();}
}
instance = new myclassB;
instance.methodB();
and :
class myclassA {
methodA() {console.log('I\'m a the class A method'); }
}
class myclassB {
constructor() {
this.classA = new myclassA;
}
methodB() {this.classA.methodA();}
}
instance = new myclassB;
instance.methodB();
I've always seen injection via constructor, but never as property. Thanks!
Using ES6 is there a way to apply multiple mixins which are defined in an array? The mixins would be defined as such:
const mixins = Array('Mixin', 'Mixin2');
Then creating a mixin with:
export const Mixin = function (superClass) {
return class extends superClass {}
And using the mixin with:
export class MyClass extends MultipleMixins(BaseClass)
You can use reduce() over the array of mixins, pass in a base class and keep returning a new mixed class. This will just apply all the mixing in order:
class BaseClass {
constructor(name) {
this.name = name
}
}
// adds an uppercase
const Mixin = function(superClass) {
return class extends superClass {
get uppercase() {
this.name = this.name.toUpperCase()
return this
}
}
}
//adds a reverse
const Mixin2 = function(superClass) {
return class extends superClass {
get reverse() {
this.name = [...this.name].reverse().join('')
return this
}
}
}
let mixins = [Mixin, Mixin2]
let MixedClass = mixins.reduce((base, mix) => mix(base), BaseClass)
let instance = new MixedClass('mark')
// use the new methods
console.log("reversed & uppercase:", instance.uppercase.reverse.name)
is there a restriction on multi level inheritance with es6 classes. I am adding some additional functionality to a framework/ external class.
class B extends External.A {
// ...
}
class C extends B {
// ...
}
and use like
const result = new C(data);
gives error
TypeError: Class constructor B cannot be invoked without 'new'
But, if I use class A directly, there is no error
class C extends External.A {
// ...
}
const result = new C(data);
// works fine
Edit:
I use "babel": "^6.5.2" to transpile everything. In real code, all 3 classes lives in different file and uses module system to export and import them. if that matters.
Original answer
Bare bones of your problem works like charm.
Probably your code is lack of super() in constructor()
class A {
constructor() {
document.write('from A <br/>');
}
}
class B extends A {
constructor() {
super();
document.write('from B <br/>');
}
}
class C extends B {
constructor() {
super();
document.write('from C <br/>');
}
}
new C();
Here is fiddle you can play with: https://jsfiddle.net/nkqkthz2/
Edit
In your original question you pass some data to C class constructor new C(data);, then if you want to handle this in your chain of classes, you should write own constructor function:
class A {
constructor(data) {
document.write(`${data} A <br/>`);
}
}
class B extends A {
someFunc() {
//
}
}
class C extends B {
constructor(data) {
super(data);
this.data = data;
}
write() {
document.write(`${this.data} C <br/>`);
}
}
const c = new C('test');
c.write();
https://jsfiddle.net/rwqgm9n0/
Pay attention that class B you don't need specify constructor since default constructor is:
constructor(...args) {
super(...args);
}
and this can pass data to class A constructor.
If you omit super in class C constructor you newer pass data to class A which can produce your error.
class A {
constructor(data) {
document.write(`${data} A <br/>`);
}
}
class B extends A {
someFunc() {
//
}
}
class C extends B {
constructor(data) {
//super(data);
this.data = data;
}
write() {
document.write(`${this.data} C <br/>`);
}
}
const c = new C('test');
c.write();
https://jsfiddle.net/jwm5xjcp/
Multilevel Inheritance:
class Person{
constructor(firstName, middleName, lastName){
console.log("Person constructor........");
this.firstName=firstName;
this.middleName=middleName;
this.lastName=lastName;
}
fullName() {
return `${this.firstName}${this.middleName==null?' ':' '+this.middleName+' '}${this.lastName}`;
}
}
//let person = new Person("FirstName",null, "LastName");
//console.log('Full Name: '+person.fullName());
// INHERITANCE
class Employee extends Person{
constructor(employeeId, joinDate,firstName, middleName, lastName){
super(firstName, middleName, lastName);
console.log("Employee constructor........");
this.employeeId = employeeId;
this.joinDate = joinDate;
}
}
/*let employee = new Employee(12, '2017-02-01', "FirstName",null, "LastName");
console.log('Full Name: '+employee.fullName());
console.log('Employee ID: '+employee.employeeId);
console.log('Join Date: '+employee.joinDate);*/
class EmpOne extends Employee{
constructor(empOneId,employeeId, joinDate,firstName, middleName, lastName){
super(employeeId, joinDate,firstName, middleName, lastName);
console.log("EmpOne constructor.........");
this.empOneId = empOneId;
}
}
let newEmpOne = new EmpOne("emp one ID", 13, '2018-02-01', "FirstName",null, "LastName");
console.log("==================================")
console.log('Full Name: '+newEmpOne.fullName());
console.log('Employee ID: '+newEmpOne.employeeId);
console.log('Join Date: '+newEmpOne.joinDate);
console.log('EMP ONE: '+newEmpOne.empOneId);
I have a base class :
class Base {
constructor() {
this.name = "base_class"
}
getBaseName() {
return "base"
}
}
and a Derived class
var _ = require('lodash');
class Derived {
constructor() {
this.name = "derived"
}
getDerivedName() {
return "derived"
}
}
_.extend(Derived.prototype, Base)
I was expecting to have getBaseName available in the derived class. But its not the case. What should I do for that? What am I missing?
var derived = new Derived();
console.log(derived.getBaseName)
-- undefined
Why are you using lodash to extend ES6 classes? Can't you just use the extends keyword?
class Derived extends Base {
constructor() {
super();
this.name = "derived"
}
getDerivedName() {
return this.name;
}
}