Reputation: 148
A method from an inherited class should return the object type from who has inherited. In C++ this behaviour is easy to accomplish. But I don't know how to do it in javascript. I know it is wrong but I wrote like this.
class A {
someMethod() {
return new A();
}
}
class B extends A {
}
var b = new B();
b.someMethod() // should return an object of type B not A
in C++ this is easy to do
template <typename c>
struct a
{
a() : _value(NULL) {}
a(std::string v) : _v(v) {}
static c* from_string(std::string &v)
{
return new c(v);
}
private:
std::string _v;
};
struct b : public a<b>
{
b() : b<a>() {}
b(std::string &v) : node<b>(a) {}
};
How should this be implemented using javascript?
This is not how inherits a class, is a particular pattern of inheriting and creating objects. There are several examples like Buffer.from
, Buffer.alloc from Node.Js. But I would like to reproduce this from a base class.
A guy showed me that my issue could be solved using the following script:
class A {
method() { return this.constructor(); }
}
class B {}
var b = new B();
var b1 = b.method();
What I really would like to do is something like following.
class A {
static from() { return new this.constructor() }
};
class B extends A {};
a = A.from();
b = B.from();
a instanceof A // should be true
b instanceof B // should be true.
I found something.
I found in typescript the same C++ behaviour can be archived as follows:
class a {
static from<t extends a>(c: { new(): t }) : t {
return new c();
}
};
class b extends a {
}
let b1 = a.from(b);
b1 instanceof b
b1 instanceof a
console.log(b1);
the es6 equivalent is:
class a {
static from(c) {
return new c();
}
}
;
class b extends a {
}
let b1 = a.from(b);
b1 instanceof b;
b1 instanceof a;
console.log(b1);
//# sourceMappingURL=index.js.map
Upvotes: 0
Views: 111
Reputation: 56467
As I've commented: a template class in C++ is actually a metaclass. It is used for constructing other classes out of it.
So we can apply this observation to JavaScript. I've played around and here's the closest thing I could get. First define a "template":
function TemplateA(cls) {
class A {
static from() {
return new cls();
};
foo() {
return -1;
};
};
return A;
};
Now define custom "extends":
function Extends(base, derived) {
// Update statics
// (these should not be overwritten)
var common = {name: 1, prototype: 1, length: 1};
var statics = Object.getOwnPropertyNames(base)
.filter(el => !common[el]);
statics.forEach(el => {
derived[el] = base[el];
});
// Update instance methods
var instanceMethods = Object.getOwnPropertyNames(base.prototype);
instanceMethods.forEach(el => {
derived.prototype[el] = base.prototype[el];
});
};
and finally usage:
class B {
test() { return 1; }
};
> Extends(TemplateA(B), B);
> var b = B.from();
> b instanceof B;
true
> var x = new B();
> x.foo();
-1
> x.test();
1
It seems to do what you want. This has some drawbacks though. It is not really an inheritance (the prototype is just updated). In particular B
is not a subclass of A<B>
(actually no such class even exists after Extends
). On the other hand JavaScript's inheritance/prototyping is quite unique and very different from C++ and so we can't expect everything to work.
Side notes:
Upvotes: 2