2012-03-07 5 views
0

Я работаю над своим первым проектом Node.js, и я пришел к проблеме ООП, и я не уверен, как решить ее в Node.js.Загрузка параметризованного модуля в Node.js

У меня есть модуль A:

module.exports = A; 

function A() { 
} 
A.prototype.method = function() { return "A";}; 
//other methods... 

и пара других модулей (позволяет сказать, В и С), которые реализуют тот же "интерфейс", как А.

Теперь у меня есть модуль X:

module.exports = X; 

function X(impl) { 
    //choose A, B, or C based on value of impl 
} 

Таким образом, вопрос, как я могу реализовать X для того, чтобы быть в состоянии сделать:

var X = require("x"); 
var impl = new X("A"); 
impl.method(); //returns "A" 

Я считаю, что prototype и __proto__ будут задействованы?

Редактировать: То, что я пытаюсь достичь, - это реализация нагрузки A, B или C на основе некоторого строкового значения (переменная ENV) через стандартизованный интерфейс new X(), а затем методы доступа A (B, C ...) к этому пример X.

+0

да? возможно, это ваш пример кода, но вы, похоже, не понимаете, как это работает. Или я не понимаю, что вы пытаетесь выполнить. См. Мой ответ за то, что я думаю, что вы пытаетесь сделать. –

+1

X должен иметь фабричный метод, вы должны вернуть либо новый A, новый Bor новый C из X.create (A_B_or_C). – mpm

ответ

2

Я думаю, что это то, что вы после:

A.js (B.js и C.js похожи, конечно):

function A() {} 

A.prototype.method = function() { 
    return 'A'; 
}; 

module.exports = A; 

X.js:

var modules = { 
    A: require('./A'), 
    B: require('./B'), 
    C: require('./C') 
} 

function X(impl) { 
    if(impl in modules) 
     return new modules[impl]; 
    else 
     throw new Error('Unknown impl: ' + impl); 
} 

module.exports = X; 

Использование:

var foo = new X('A'); 
foo.method(); 
// => 'A' 
var bar = new X('B'); 
bar.method() 
// => 'B' 

альтернатива keepi нг modules объект в X является require внутри X(impl) и пусть require бросить ошибку:

function X(impl) { 
    return new require('./' + impl); 
} 
+1

Это в значительной степени, как я тоже это сделаю.Еще одно потенциальное улучшение, если вы хотите сделать свою собственную обработку ошибок, но не хотите, чтобы массив модулей (например, вы планируете добавлять D, E, F и т. Д. Довольно часто) будет использовать require.resolve() чтобы гарантировать, что запрошенный модуль существует до фактического его требования, без необходимости искать его в своем собственном массиве известных модулей. –

+0

Я действительно узнал, что последний бит, который у вас там есть, НЕ будет работать. По какой-то причине, если вы не измените ее на 'function X (impl) { var x = new require ('./' + impl); return x; } '' 'foo.method()' будет вызывать ошибку, говоря, что у объекта нет метода. –

0
//x.js 
module.exports = function(a) { 
    return a; 
} 

//a.js 
modules.exports = function() { 
return {method: function() { return "A" } }; 
} 

var X = require("x"); 

var impl = new X(require("a")); 

impl.method(); //returns "A" 

Это правильно?

+0

Ну, вроде. Кроме того, я не могу назвать 'impl.method()', поскольку он был объявлен в прототипе A. Кроме того, это не вызовет конструкторы как для X, так и для A –

+0

, поскольку данные не являются строго типизированными. Это должно быть просто, просто скопируйте свои прототипы в качестве аргументов для требования x, тогда вы можете вернуть экземпляр любого из этих классов. –

1

Чтобы вызвать родительский конструктор, вам необходимо на самом деле вызвать/применить его в контексте нового объекта. См. [1].

Чтобы наследовать методы, вам необходимо клонировать прототип из родительского класса в дочерний класс. См. [2]

// parentclass.js 
var ParentClass = function (arg) { 
    console.log("Calling ParentClass constructor with " + arg); 
}; 

ParentClass.prototype.method = function (arg) { 
    console.log("Calling ParentClass method with " + arg); 
}; 

// childclass.js 
var ChildClass = function() { 
    console.log("Calling ChildClass constructor"); 
    // [1] 
    ParentClass.apply(this, arguments); 
}; 

// [2] 
ChildClass.prototype = Object.create(ParentClass.prototype); 

var instance = new ChildClass('some argument'); 
instance.method('ahahahah'); 

Это именно то, что вам нужно?

+0

+1 отлично описание –

+0

спасибо. О, я забыл экспортировать 'var ParentClass = module.exports = ...'. – kevin

Смежные вопросы