Welcome to wechat public account: Front Reading Room
introduce
In addition to the traditional object-oriented inheritance approach, a popular way to create classes from reusable components is to combine the code of another simple class. You may be familiar with mixins and their features in languages like Scala, but they are also popular in JavaScript.
With the sample
The following code demonstrates how to use mixin in TypeScript. We’ll explain how this code works later.
// Disposable Mixin
class Disposable {
isDisposed: boolean;
dispose() {
this.isDisposed = true; }}// Activatable Mixin
class Activatable {
isActive: boolean;
activate() {
this.isActive = true;
}
deactivate() {
this.isActive = false; }}class SmartObject implements Disposable.Activatable {
constructor() {
setInterval(() = > console.log(this.isActive + ":" + this.isDisposed), 500);
}
interact() {
this.activate();
}
// Disposable
isDisposed: boolean = false;
dispose: () = > void;
// Activatable
isActive: boolean = false;
activate: () = > void;
deactivate: () = > void;
}
applyMixins(SmartObject, [Disposable, Activatable]);
let smartObj = new SmartObject();
setTimeout(() = > smartObj.interact(), 1000);
////////////////////////////////////////
// In your runtime library somewhere
////////////////////////////////////////
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor= > {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name= > {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
Copy the code
Understand this example
The code first defines two classes that will serve as mixins. You can see that each class defines only one specific behavior or function. We’ll use them later to create a new class that does both.
// Disposable Mixin
class Disposable {
isDisposed: boolean;
dispose() {
this.isDisposed = true; }}// Activatable Mixin
class Activatable {
isActive: boolean;
activate() {
this.isActive = true;
}
deactivate() {
this.isActive = false; }}Copy the code
Let’s create a class that combines these two mixins. Here’s how it works:
class SmartObject implements Disposable.Activatable {
Copy the code
The first thing you should notice is that implements is used instead of extends. The class is treated as an interface, using only the types of Disposable and Activatable instead of their implementations. This means that we need to implement interfaces in our classes. But that’s what we want to avoid when we use mixins.
We can do this by creating placeholder properties for the property methods that will be mixin. This tells the compiler that these members are available at run time. This allows you to take advantage of mixins, although some placeholder attributes need to be defined in advance.
// Disposable
isDisposed: boolean = false;
dispose: () = > void;
// Activatable
isActive: boolean = false;
activate: () = > void;
deactivate: () = > void;
Copy the code
Finally, mixins are mixed into the defined classes to complete the implementation.
applyMixins(SmartObject, [Disposable, Activatable]);
Copy the code
Finally, create this helper function to help us with blending. It iterates over all the mixins’ properties and copies them to the target, replacing the placeholder properties with the actual implementation code.
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor= > {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name= >{ derivedCtor.prototype[name] = baseCtor.prototype[name]; })}); }Copy the code
Welcome to wechat public account: Front Reading Room