2013-07-21 5 views
4

Я пытаюсь найти лучший подход к нескольким уровням наследования при использовании класса Node.js EventEmitter.Node.js EventEmitter и несколько уровней наследования

Установка Я разрабатываю структуру MVC для Node.js, используя контроллеры, которые могут иметь базовые контроллеры, но контроллеры могут генерировать события, которые также генерируют одно и то же событие на его базовом контроллере. До сих пор у меня есть:

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» выводится, я хочу как «запрос» события на огонь. Как мне это сделать? Может, мне нужно полностью изменить свой подход?


Update: спасибо за помощь всем. Как предположил Наор Битон, не было наследования между baseController и homeController, потому что свойство «prototype» имеет значение только для функций конструктора. Я всегда получаю, что мои функции конструктора и экземпляры объектов перепутаны.

В конце концов я остановился на следующем:.

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'); 
+0

Это не похоже на (прототипное) наследование, но больше похоже на составной узор. – Bergi

ответ

3

В вашем примере, нет никакого вида наследования отношений между HomeController и baseController. Кроме того, эта строка:

homeController.prototype = baseController; 

Резервирован, поскольку свойство прототипа имеет значение только для функций конструктора.

Если вы хотите настроить baseController так, кто простирается/наследует от него будет «запрос» слушателя, возложенные на него, сначала вы должны определить это так:

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

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

Это будет даже лучше, если вы можете сделать назначение обработчика в методе initiliazation (делает работу в функции конструктора, как правило, плохой дизайн):

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 не очень хорошо или ремонтопригодны. Если вы можете, я рекомендую вам избежать этого и попытаться найти более удобное решение.

2

В вашем примере как homeController и baseController имеют один и тот же прототип (который вы можете проверить с помощью getPrototypeOf.prototypeis an attributes of functions

Если вы хотите установить. прототип объекта другому объекту напрямую, без использования функции и установки его прототипа, вы можете использовать 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"); 
+0

В вашем примере после 'var obj = new Controller();', ** obj ** нигде не используется. Как работает ** HomeController **, связанный с ** Контроллером **? –

+0

@NaorBiton Спасибо, пропало без ответа :) –

+0

@NaorBiton Ваше изменение к этому сообщению было отклонено (рецензенты, вероятно, пропустили комментарии здесь), я исправил сейчас - спасибо agian. –