Advanced JavaScript Inheritance in TypeScript
One of the wonderful aspects of JavaScript is the number of different ways objects can inherit encapsulation from others. However, TypeScript puts heavy constraints on the possibilities for writing a module, from this perspective.
In JavaScript, you have the option to achieve Multiple Inheritance -- rather, Mixin functionality -- through the use of Constructor Hijacking, which is an extremely powerful feature of the language:
var Base = function Base() {
function f() {
console.log('datum: %s', this.datum);
}
function method() {
this.a();
this.b();
this.c();
}
// export precepts
this.datum = true;
this.f = f;
this.method = method;
return this;
};
var A = function A() {
function a() {
this.f();
}
// export precepts
this.a = a;
return this;
};
var B = function B() {
function b() {
this.f();
}
// export precepts
this.b = b;
return this;
};
var C = function C() {
function c() {
this.f();
}
// export precepts
this.c = c;
return this;
};
var Klass = function Klass() {
var config = { };
function init() {
this.method();
}
// export precepts
Base.call(this);
A.call(this);
B.call(this);
C.call(this);
this.config = config;
this.init = init;
return this;
};
var klass = new Klass();
klass.init();
// > datum: true
// > datum: true
// > datum: true
This allows a developer to break their code out in discrete modules that only need follow a pattern or convention in order to extend another module, keeping the Single Responsibility Principle and the Open-Close Principle of SOLID pristine.
Analysis
The code above should log the string datum: true
3 times. This is because Klass
decorates (or mixes-in) the Base
class so that classes A-C
do not throw a Run-Time Error as they invoke this.f
. The CallStack of the process looks something like the following:
- [Klass] init
- [Base] method
- [A] a
- [Base] f
- [Console] log
- [B] b
- [Base] f
- [Console] log
- [C] c
- [Base] f
- [Console] log
Notes
The CallStack is fairly arbitrary and trivial. Also, this code could be seen as non-SOLID, but just assume we're using The Template-Method Pattern if it helps to get around the crudeness of the example.
Also, there will undoubtedly be a soul to pipe up and say something about how everything we know about the example above violates TypeScript. Bear in mind, "TypeScript is a superset of JavaScript" is simply, plainly, and blatantly wrong -- I won't even argue why, you should already know this if you are using TypeScript.
Question:
Given the code above, how can one achieve such functionality using valid TypeScript syntax? I am also open to leveraging Design Patterns if necessary, though this is still not ideal.
Aucun commentaire:
Enregistrer un commentaire