4

我试图找出使用 Node.jsEventEmitter类时多级继承的最佳方法。

设置是我正在使用可以具有基本控制器的控制器为 Node.js 开发 MVC 框架,但控制器可以发出事件,这些事件也可以在其基本控制器上发出相同的事件。到目前为止,我有:

var events = require('events');
var util = require('util');

var Controller = function() { };
util.inherits(Controller, events.EventEmitter);

var baseController = new Controller();
baseController.on('request', function() {
    console.log('Calling request event on baseController');
});



var homeController = new Controller();
homeController.prototype = baseController;

homeController.on('request', function() {
   console.log('Calling request event on homeController'); 
});


homeController.emit('request');

...但仅输出“在 homeController 上调用请求事件”,我希望触发两个“请求”事件。我该怎么做呢?也许我需要完全改变我的方法?


更新:感谢大家的帮助。正如 Naor Biton 所建议的,baseController 和 homeController 之间没有继承关系,因为“原型”属性只对构造函数很重要。我总是把我的构造函数和对象实例混在一起。

我最终解决了以下问题:

var events = require('events');
var util = require('util');

var Controller = function() { };
util.inherits(Controller, events.EventEmitter);

Controller.createBaseController = function() {
    var BaseController = function() { };
    util.inherits(BaseController, Controller);

    return new BaseController();
};

Controller.inheritController = function(baseController) {
    var NewController = function() { };
    NewController.prototype = baseController;

    return new NewController();
};


var baseController = Controller.createBaseController();

baseController.on('request', function() {
    console.log('Calling request event on baseController');
});


var homeController = Controller.inheritController(baseController);

homeController.on('request', function() {
   console.log('Calling request event on homeController');
});


homeController.emit('request');
4

2 回答 2

3

在您的示例中, homeControllerbaseController之间没有继承关系。另外,这一行:

homeController.prototype = baseController;

是多余的,因为原型属性只对构造函数很重要。

如果您想设置baseController以便从它扩展/继承的人将分配给它的“请求”侦听器,首先您应该像这样定义它:

var BaseController = function(){
    this.on('request', function(){
       console.log('...');
    });
};

BaseController.prototype = new events.EventEmitter();
BaseController.prototype.constructor = BaseController;

如果您可以在初始化方法中进行处理程序分配,那就更好了(在构造函数中工作通常是糟糕的设计):

var BaseController = function(){};

BaseController.prototype = new events.EventEmitter();
BaseController.prototype.init = function(){
    this.on('request', function(){
       console.log('...');
    });
};

然后,您只需在HomeController中扩展它即可:

var HomeController = function(){};
HomeController.prototype = new BaseController();

var homeController = new HomeController();
homeController.init(); // If you went with the initialization approach I offered...

请注意,除非您必须这样做,否则在 JS 中创建长继承链并不是很好或可维护的。如果可以的话,我鼓励你避免这样做,并尝试找到一个更易于维护的解决方案。

于 2013-07-21T12:58:35.100 回答
2

在您的示例中,两者都homeController具有baseController相同的原型(您可以使用getPrototypeOf.验证它.prototype 函数的属性。

如果您想直接将一个对象的原型设置为另一个对象而不使用函数并设置其原型,您可以使用Object.create

顺便说一下,这是我在你的情况下要做的(使用更少的原型继承和更多的结构子类型)。

function Controller(){
    var obj = new events.EventEmitter();
    // Add stuff to controller here
    obj.on("request",function(){
            console.log('Calling request event on baseController');
    });
    return obj;
}
function HomeController(){
    var obj = new Controller();
    obj.on('request', function() {
        console.log('Calling request event on homeController'); 
    });
    return obj;
}

var homeController = new HomeController(); // can create a Controller and add 
                                           // an event just fine. If you want explicit
                                           // structural subtyping we need HomeController
homeController.emit("request");
于 2013-07-21T12:50:36.280 回答