2015-03-03 107 views
0

我試圖移植一個Java應用程序以用於node.js,並且正在運行到Object繼承的問題。我有一個基礎對象HVal和2個亞類HBin和HBool。當我嘗試同時使用HBin和HBool時,加載的第一個對象被加載的第二個對象覆蓋,即使它們被分配到不同的變量。任何人都知道這裏發生了什麼。node.js對象繼承覆蓋對象方法

HVal.js

/** Package private constructor */ 
function HVal() {}; 

/** Abstract functions that must be defined in inheriting classes 
* hashCode: int - Hash code is value based 
* toZinc: String - Encode value to zinc format 
* equals: boolean - Equality is value based 
*/ 

/** String - String format is for human consumption only */ 
HVal.prototype.toString = function() { return this.toZinc(); }; 

/** int - Return sort order as negative, 0, or positive */ 
HVal.prototype.compareTo = function(that) { return this.toString().localeCompare(that); }; 

/** boolean - check for type match */ 
HVal.prototype.typeis = function (check, prim, obj) { return typeof(check)==prim || check instanceof obj; }; 

/** Add hashCode function to Javascript String object */ 
String.prototype.hashCode = function() { 
    var hash = 0, i, chr, len; 
    if (this.length == 0) return hash; 
    for (i = 0, len = this.length; i < len; i++) { 
    chr = this.charCodeAt(i); 
    hash = ((hash << 5) - hash) + chr; 
    hash |= 0; // Convert to 32bit integer 
    } 
    return hash; 
}; 

/** Export for use in other modules */ 
module.exports = new HVal(); 

HBin.js

var hval = require('./HVal'); 

/** Private constructor */ 
function HBin(mime) { 
    /** MIME type for binary file */ 
    this.mime = mime; 
}; 
HBin.prototype = hval; 

/** Construct for MIME type */ 
HBin.prototype.make = function(mime) { 
    if (!hval.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0) 
    throw new Error("Invalid mime val: \"" + mime + "\""); 
    return new HBin(mime); 
}; 

/** int - Hash code is based on mime field */ 
HBin.prototype.hashCode = function() { return mime.hashCode(); }; 

/** String - Encode as "Bin(<mime>)" */ 
HBin.prototype.toZinc = function() { 
    var s = "Bin("; 
    for (var i=0; i<this.mime.length; ++i) 
    { 
    var c = this.mime.charAt(i); 
    if (c > 127 || c == ')') throw new Error("Invalid mime, char='" + c + "'"); 
    s += c; 
    } 
    s += ")"; 
    return s.toString(); 
}; 

/** boolean - Equals is based on mime field */ 
HBin.prototype.equals = function(that) { 
    if (!typeOf(that) == HBin) return false; 
    return this.mime === that.mime; 
}; 

/** Export for use in other modules */ 
module.exports = new HBin(); 

HBool.js

var hval = require('./HVal'); 

/** Private constructor */ 
function HBool(val) { 
    /** Boolean value */ 
    this.val = val; 
}; 
HBool.prototype = hval; 

/** Construct from boolean value */ 
HBool.prototype.make = function(val) { 
    if (!hval.typeis(val, 'boolean', Boolean)) 
    throw new Error("Invalid boolean val: \"" + val + "\""); 
    return new HBool(val); 
}; 

/** int - Hash code is same as java.lang.Boolean */ 
HBool.prototype.hashCode = function() { return this.val ? 1231 : 1237; }; 

/** String - Encode as T/F */ 
HBool.prototype.toZinc = function() { return this.val ? "T" : "F"; }; 

/** boolean - Equals is based on reference */ 
HBool.prototype.equals = function(that) { return this === that; }; 

/** String - String format is for human consumption only */ 
HBool.prototype.toString = function() { return this.val ? "true" : "false"; }; 

/** Export for use in other modules */ 
module.exports = new HBool(); 

index.js

var hbin = require('./HBin'); 
var hbool = require('./HBool'); 

console.log('BIN: ' + hbin.make("test/test").toString()); 
console.log(); 
console.log('T: ' + hbool.make(true).toString()); 
console.log('F: ' + hbool.make(false).toString()); 

輸出 - 未能在第一次的console.log

HBool.js:19 
    throw new Error("Invalid boolean val: \"" + val + "\""); 
Error: Invalid boolean val: "test/test" 
    at HVal.HBool.make (HBool.js:19:11) 
    at Object.<anonymous> (index.js:4:28) 
    ... 

回答

1

問題與如何您是從模塊輸出,以及如何當你要繼承和問題是很微妙的,你要指定原型做。這裏有一些事情正在進行。首先,module.exports被緩存模塊,所以每次做:

var hval = require('./HVal'); 

你得到完全相同的HVal每次實例化的對象回來,你也沒辦法讓不同的對象,因爲你沒有出口的構造。這是所有模塊的問題。您應該導出構造函數並讓模塊的用戶實際上使用new創建對象的新實例。

你可以做到這一點的改變:

module.exports = new HVal(); 

到:

module.exports = HVal; 

而且,然後當你require()它,你剛纔得到的構造:

var HVal = require('./HVal'); 
var HBool = require('./HBool'); 

而且,那麼你可以創建一個這樣的對象:

var hbool = new HBool(); 

這個問題,那麼似乎搞亂了你的產業,當你分配是這樣的:

HBool.prototype = hval; 

如果導出構造函數本身,然後更改上述原型分配的問題完全固定使用的Object.create:

HBool.prototype = Object.create(HVal.prototype); 

你可以在這裏看到一個工作演示(模塊去掉,使演示更容易顯示): http://jsfiddle.net/jfriend00/ty5wpkqm/


我還對代碼進行了另一次更正。取而代之的是:

if (!hval.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0) 

我改成了實際使用此對象的繼承方法:

if (!this.typeis(mime, 'string', String) || mime.length == 0 || mime.indexOf('/') < 0) 

這是調用當前對象(甚至繼承的方法)上的方法的正確方法。現在,這恰好是一種靜態方法(它根本不使用實例,因此您可以完全將其從對象上移除,但由於您已將其聲明在對象上,因此應將其稱爲this.typeis()


我還注意到,您的.equals()方法不正確你有這樣的:

/** boolean - Equals is based on mime field */ 
HBin.prototype.equals = function(that) { 
    if (!typeOf(that) == HBin) return false; 
    return this.mime === that.mime; 
}; 

首先,你有沒有創建一個名爲typeOf()一個新的全局函數在JavaScript中內置的機制是小寫typeof?其次,typeof(that)將永遠不會爲HBin。在Javascript中不報告這種類型。一個對象會報告typeof(that) === "object"。你或許可以使用instanceof

/** boolean - Equals is based on mime field */ 
HBin.prototype.equals = function(that) { 
    return that instanceof HBin && this.mime === that.mime; 
}; 
+0

這時候,當分離到了4個個別所有的代碼合併到一個單一的文件,而不是工作。當分開時,我收到錯誤: 'HBin.prototype = Object.create(HVal.prototype); TypeError:對象原型可能只是一個對象或null:undefined' – 2015-03-03 08:17:01

+0

@ShawnJacobson - 你是否改變你的'module.exports'我如何解釋?如果你正確地做到了,它會很好地工作。你的錯誤信息是因爲'HVal'(應該來自模塊導出)不是正確的值。 – jfriend00 2015-03-03 08:21:21

+0

我的不好。我很接近,但忘了移動「新」關鍵字,我只刪除了括號。謝謝@ jfriend00 !!! – 2015-03-03 08:24:45