1 |
|
2 | var aggregation = (baseClass, ...mixins) => {
|
3 | let base = class _Combined extends baseClass {
|
4 | constructor (...args) {
|
5 | super(...args);
|
6 | mixins.forEach((mixin) => {
|
7 | mixin.prototype.initializer.call(this);
|
8 | });
|
9 | }
|
10 | };
|
11 | let copyProps = (target, source) => {
|
12 | Object.getOwnPropertyNames(source)
|
13 | .concat(Object.getOwnPropertySymbols(source))
|
14 | .forEach((prop) => {
|
15 | if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
|
16 | return
|
17 | Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
|
18 | })
|
19 | }
|
20 | mixins.forEach((mixin) => {
|
21 | copyProps(base.prototype, mixin.prototype);
|
22 | copyProps(base, mixin);
|
23 | });
|
24 | return base;
|
25 | };
|
26 |
|
27 | class Colored {
|
28 | initializer () { this._color = "white"; }
|
29 | get color () { return this._color; }
|
30 | set color (v) { this._color = v; }
|
31 | }
|
32 |
|
33 | class ZCoord {
|
34 | initializer () { this._z = 0; }
|
35 | get z () { return this._z; }
|
36 | set z (v) { this._z = v; }
|
37 | }
|
38 |
|
39 | class Shape {
|
40 | constructor (x, y) { this._x = x; this._y = y; }
|
41 | get x () { return this._x; }
|
42 | set x (v) { this._x = v; }
|
43 | get y () { return this._y; }
|
44 | set y (v) { this._y = v; }
|
45 | }
|
46 |
|
47 | class Rectangle extends aggregation(Shape, Colored, ZCoord) {}
|
48 |
|
49 | var rect = new Rectangle(7, 42);
|
50 | rect.z = 1000;
|
51 | rect.color = "red";
|
52 | console.log(rect.x, rect.y, rect.z, rect.color);
|