来自C ++ / Java背景,CoffeeScript中的OOP-Inheritance使我感到困惑。
考虑以下示例:
class BaseClass
arr: []
addItem: (item) =>
@arr.push item
class SubClassA extends BaseClass
constructor: ->
@addItem("fromSubA")
class SubClassB extends BaseClass
console.log "Case 1"
instB = new BaseClass()
instA = new SubClassA()
console.log "instA: #{JSON.stringify instA.arr}"
console.log "instB #{JSON.stringify instB.arr}"
console.log "Case 2"
instB = new SubClassB()
instA = new SubClassA()
console.log "instA: #{JSON.stringify instA.arr}"
console.log "instB #{JSON.stringify instB.arr}"
console.log "Case 3"
instB = new SubClassB()
instA = new SubClassA()
console.log "instA: #{JSON.stringify instA.arr}"
console.log "instB #{JSON.stringify instB.arr}"
tinkerbin.com的输出:
Case 1
instA: ["fromSubA"]
instB ["fromSubA"]
Case 2
instA: ["fromSubA","fromSubA"]
instB ["fromSubA","fromSubA"]
Case 3
instA: ["fromSubA","fromSubA","fromSubA","Added manually, only to instB"]
instB ["fromSubA","fromSubA","fromSubA","Added manually, only to instB"]
Iow:基类的'arr'实例属性或多或少都像静态属性;如果我在一个实例中更改了数组,那么它在另一个实例中也会更改。 为什么在实例之间共享此数组?
令人困惑的是,字符串属性不会出现此行为:
class BaseClass
property: "From Base"
class SubClassA extends BaseClass
constructor: ->
@property = "fromSubClassA"
class SubClassB extends BaseClass
document.write "Case 1<br>"
instB = new BaseClass()
instA = new SubClassA()
document.write "#{instA.property} <br>"
document.write "#{instB.property} <br><br>"
document.write "Case 2<br>"
instB = new SubClassB()
instA = new SubClassA()
instA.property = "test"
document.write "#{instA.property} <br>"
document.write "#{instB.property} <br>"
此代码工作正常,保持实例之间的'property'属性。
我显然在这里误解了一些东西。是什么导致数组在实例之间共享?
答案 0 :(得分:2)
看一下生成的JavaScript的样子:
var BaseClass,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
BaseClass = (function() {
function BaseClass() {
this.addItem = __bind(this.addItem, this);
}
BaseClass.prototype.arr = [];
return BaseClass;
})();
如您所见,arr
是BaseClass
的原型的属性,就像Python等语言中的类变量一样。该类中只有一个实例存在并且在该类的所有实例之间共享,因此如果您对其进行修改,则会对其进行修改(通过访问instance.arr
,您将遍历原型链到同一个{{1数组)。
字符串在JavaScript中是不可变的,因此它们在这方面的行为不像数组。
答案 1 :(得分:2)
在您的示例中,arr
是一个类(即静态)属性变量,因此它与BaseClass
的所有实例共享。
您需要修改BaseClass
并在arr
方法中初始化constructor
属性:
class BaseClass
constructor: ->
@arr = []
addItem: (item) =>
@arr.push item
然后,您要确保SubClassA
使用BaseClass
关键字调用super()
开发者:
class SubClassA extends BaseClass
constructor: ->
super()
@addItem("fromSubA")