2

C++/Java のバックグラウンドを持つ私は、CoffeeScript の OOP 継承に戸惑いました。

次の例を検討してください。

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: base-class の「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>"

このコードは問題なく機能し、「プロパティ」プロパティをインスタンス間で分離したままにします。

私は明らかにここで何かを誤解しています。アレイがインスタンス間で共有される原因は何ですか?

4

2 に答える 2

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プロパティであり、Python などの言語のクラス変数と同じです。その配列のインスタンスは 1 つだけ存在し、そのクラスのすべてのインスタンス間で共有されます。したがって、それを変更すると、どこでも変更されます ( にアクセスすることで、同じ配列までプロトタイプ チェーンをたどることになります)。BaseClassinstance.arrBaseClass.prototype.arr

文字列は JavaScript では不変であるため、その点では配列のようには動作しません。

于 2013-06-12T15:29:02.967 に答える
2

あなたの例arrでは、クラス(つまり静的)プロパティ変数であるため、BaseClass.

メソッドでプロパティを編集してBaseClass初期化する必要があります。arrconstructor

class BaseClass
    constructor: ->
        @arr = []

    addItem: (item) =>
        @arr.push item

次に、キーワードを使用してコストラクタをSubClassA呼び出していることを確認します。BaseClasssuper()

class SubClassA extends BaseClass
    constructor: ->
        super()
        @addItem("fromSubA")
于 2013-06-12T15:57:39.583 に答える