如何在 NodeJS 中将事件添加到 derived/child class?
How to add events to a derived/child class in NodeJS?
我有一个 child class 扩展 parent class。我还希望 child class 能够发出事件。我发现的例子是扩展 EventEmitter。但是JS不允许多重继承。我试图通过 mixin 实现它,但不确定如何不将我的 parent class 转换为 mixin。
示例
假设有一个载具基地 class
所有车辆都会移动,有些车辆会在移动时发出事件
class Vehicle {
constructor(name) { this.name = name }
move() { console.log(this.name, 'Moved'); }
}
class Car extends Vehicle {
constructor() { super('Ford'); }
move() {
super.move();
this.engineSound();
}
engineSound() {
console.log("Vroooom!");
}
// some other car related properties
}
class Ambulance extends Vehicle { // want to extend EventEmitter aswell
constructor() { super('Ambulance1'); }
move() {
super.move();
// emit moved event here
}
}
let normalVehicle = new Vehicle('Normal');
normalVehicle.move();
let car = new Car();
car.move();
let ambulance = new Ambulance();
// Listen for moving ambulance here
// ambulance.on('moved', () => { console.log('Ambulance coming') });
ambulance.move();
但是要发出事件文档建议扩展 EventEmitter 但 JS 不支持扩展多个 classes。
看到几个使用 Object.assign
的示例,但不确定如何在此处应用。
es6 class 语法根本不支持多重继承。如果您将所有 classes 转换为 es5 构造函数,然后使用 Object.assign 之类的东西,您可以尝试一些奇怪的技巧。但最好的方法是使用组合而不是继承。
OOP 用于尝试模拟真实世界的对象,因此在现实世界中,救护车本身就是事件发射器也没有意义。
但是,使用组合方法,救护车 具有 事件发射器(如收音机或其他此类传输设备)是有意义的:
class Ambulance extends Vehicle {
#radio = new EventEmitter();
constructor() {
super("Ambulance");
}
emit(event) { this.#radio.emit(event) }
on(event, handler) { this.#radio.on(event, handler) }
move() {
super.move();
this.emit("moved");
}
}
let ambulance = new Ambulance();
ambulance.on('moved', () => { console.log('Ambulance coming') });
ambulance.move();
请注意,收音机是私有的(使用新的 JS 私有字段功能),我只为我希望救护车用户拥有的确切功能提供外观,在本例中 'on' 和 'emit'.
话虽如此...
让我们疯狂并实际回答您的问题!同样,这将需要使用 es5 构造函数:
// Base class - no inheritance
var Vehicle = (function () {
function Vehicle(name) {
this.name = name;
}
Vehicle.prototype.move = function () {
return this.name + " Moved\n";
};
return Vehicle;
})();
// Derived from Vehicle - regular inheritance from a single object
var Car = (function (_super) {
function Car() {
// Calling super() in constructor
_super.call(this, "Ford");
}
// extend Vehicle
Car.prototype = Object.create(Vehicle.prototype);
// bring back Car's constructor, because last step overrid it
Object.defineProperty(Car.prototype, "constructor", {
value: Car,
enumerable: false,
writable: true,
configurable: true
});
Car.prototype.move = function () {
return _super.prototype.move.call(this) + this.engineSound();
};
Car.prototype.engineSound = function () {
return "Vroooom!\n";
};
return Car;
})(Vehicle);
// Derived from Vehicle and EventEmitter - multiple inheritance!
var Ambulance = (function (_superVehicle, _superEventEmitter) {
function Ambulance() {
_superVehicle.call(this, "Ambulance");
_superEventEmitter.call(this);
}
// Create joint prototype using Object.assign
var jointPrototype = Object.assign(
{},
_superEventEmitter.prototype,
_superVehicle.prototype
);
// Connecting Ambulance to prototype chain
Ambulance.prototype = Object.create(jointPrototype);
// restore Ambulance's constructor
Object.defineProperty(Ambulance.prototype, "constructor", {
value: Ambulance,
enumerable: false,
writable: true,
configurable: true
});
Ambulance.prototype.move = function () {
this.emit("moved");
return _superVehicle.prototype.move.call(this);
};
return Ambulance;
})(Vehicle, EventEmitter);
我有一个 child class 扩展 parent class。我还希望 child class 能够发出事件。我发现的例子是扩展 EventEmitter。但是JS不允许多重继承。我试图通过 mixin 实现它,但不确定如何不将我的 parent class 转换为 mixin。
示例
假设有一个载具基地 class 所有车辆都会移动,有些车辆会在移动时发出事件
class Vehicle {
constructor(name) { this.name = name }
move() { console.log(this.name, 'Moved'); }
}
class Car extends Vehicle {
constructor() { super('Ford'); }
move() {
super.move();
this.engineSound();
}
engineSound() {
console.log("Vroooom!");
}
// some other car related properties
}
class Ambulance extends Vehicle { // want to extend EventEmitter aswell
constructor() { super('Ambulance1'); }
move() {
super.move();
// emit moved event here
}
}
let normalVehicle = new Vehicle('Normal');
normalVehicle.move();
let car = new Car();
car.move();
let ambulance = new Ambulance();
// Listen for moving ambulance here
// ambulance.on('moved', () => { console.log('Ambulance coming') });
ambulance.move();
但是要发出事件文档建议扩展 EventEmitter 但 JS 不支持扩展多个 classes。
看到几个使用 Object.assign
的示例,但不确定如何在此处应用。
es6 class 语法根本不支持多重继承。如果您将所有 classes 转换为 es5 构造函数,然后使用 Object.assign 之类的东西,您可以尝试一些奇怪的技巧。但最好的方法是使用组合而不是继承。
OOP 用于尝试模拟真实世界的对象,因此在现实世界中,救护车本身就是事件发射器也没有意义。
但是,使用组合方法,救护车 具有 事件发射器(如收音机或其他此类传输设备)是有意义的:
class Ambulance extends Vehicle {
#radio = new EventEmitter();
constructor() {
super("Ambulance");
}
emit(event) { this.#radio.emit(event) }
on(event, handler) { this.#radio.on(event, handler) }
move() {
super.move();
this.emit("moved");
}
}
let ambulance = new Ambulance();
ambulance.on('moved', () => { console.log('Ambulance coming') });
ambulance.move();
请注意,收音机是私有的(使用新的 JS 私有字段功能),我只为我希望救护车用户拥有的确切功能提供外观,在本例中 'on' 和 'emit'.
话虽如此...
让我们疯狂并实际回答您的问题!同样,这将需要使用 es5 构造函数:
// Base class - no inheritance
var Vehicle = (function () {
function Vehicle(name) {
this.name = name;
}
Vehicle.prototype.move = function () {
return this.name + " Moved\n";
};
return Vehicle;
})();
// Derived from Vehicle - regular inheritance from a single object
var Car = (function (_super) {
function Car() {
// Calling super() in constructor
_super.call(this, "Ford");
}
// extend Vehicle
Car.prototype = Object.create(Vehicle.prototype);
// bring back Car's constructor, because last step overrid it
Object.defineProperty(Car.prototype, "constructor", {
value: Car,
enumerable: false,
writable: true,
configurable: true
});
Car.prototype.move = function () {
return _super.prototype.move.call(this) + this.engineSound();
};
Car.prototype.engineSound = function () {
return "Vroooom!\n";
};
return Car;
})(Vehicle);
// Derived from Vehicle and EventEmitter - multiple inheritance!
var Ambulance = (function (_superVehicle, _superEventEmitter) {
function Ambulance() {
_superVehicle.call(this, "Ambulance");
_superEventEmitter.call(this);
}
// Create joint prototype using Object.assign
var jointPrototype = Object.assign(
{},
_superEventEmitter.prototype,
_superVehicle.prototype
);
// Connecting Ambulance to prototype chain
Ambulance.prototype = Object.create(jointPrototype);
// restore Ambulance's constructor
Object.defineProperty(Ambulance.prototype, "constructor", {
value: Ambulance,
enumerable: false,
writable: true,
configurable: true
});
Ambulance.prototype.move = function () {
this.emit("moved");
return _superVehicle.prototype.move.call(this);
};
return Ambulance;
})(Vehicle, EventEmitter);