4

EventEmitterNode.jsクラスを使用する場合、複数レベルの継承への最適なアプローチを見つけようとしています。

セットアップは、基本コントローラーを持つことができるコントローラーを使用して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');

…でも、「calling request event on homeController」しか出力されないので、両方の「 request 」イベントを発火させたい。どうすればいいですか?多分私は私のアプローチを完全に変える必要がありますか?


更新:みんなの助けに感謝します。Naor Biton が示唆したように、「prototype」プロパティはコンストラクター関数にのみ関係するため、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を持っています (これは を使用して確認できます。functionsの属性です.baseControllergetPrototypeOf.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 に答える