10

flex 3の関数を介してarrayCollection#2 =をarrayCollection#1に設定したいと思います。両方の配列コレクションを関数に渡し、arrayCollection#2 = arrayCollection#1を設定します。ただし、関数呼び出し後、arrayCollection#2は変更されていないため、参照によってarrayCollection#2を渡していないようです。私の理解では、それは参照と作業によって渡されるべきであるということです、私は何か間違ったことをしていますか?以下はコードです:

var AC1:ArrayCollection = new ArrayCollection;
var AC1.addItem(someObject);

var AC2:ArrayCollection = new ArrayCollection;

setAC2(AC1,AC2);
// AC2 is not set to AC1 after the function


private function setAC2(_ac1:ArrayCollection, _ac2:ArrayCollection):void
{
    _ac2 = _ac1;
}
4

4 に答える 4

6

評価戦略をご覧ください。

ASは「passbyobject」/「passbyobject-sharing」を使用します。つまり、「オブジェクト」が渡され(コピー、クローン、複製ではありません)、オブジェクトへの変更はすべて共有されます。

ただし、割り当て_ac2 = _ac1は[関数のローカル]パラメータ変数の値を変更するだけであり、関数の呼び出し中に変数に影響を与えることはありません。渡されるのは、関数呼び出しで使用される変数(または任意の式)の評価から得られる値(「オブジェクト」)だけです。

これは、前述のように、使用される戦略が「オブジェクトの受け渡し」であり、(ドキュメントに「参照の受け渡し」と記載されているため、実際には「[参照の]値の受け渡し」または単に...」ではないためです。オブジェクトを渡す」)。つまり、「参照渡し」という用語は実際には誤用されているため、混乱を招きます。(これは、多くの言語やドキュメントで誤用されています。共通の意味を理解しようとする困難な戦いです。)

それが本当に「参照渡し」である場合、に新しい値を割り当てる_ac2と伝播します。(ASが「参照渡し」であるというコメントを投稿する前に、上部のリンクを参照し、「参照渡し」がC#out/ref、VB ByRef、TSQL output、およびC ++(参照)の場合をカバーしていることを考慮してください。&これらの概念は含まれていません。 AS、Javascript、またはJava)。ただし、元の投稿(および追加の自己返信)に正しく記載されているように、そうではありません-結論:ASは「参照渡し」をサポートしていません。さらに、ドキュメントでは(紛らわしいことに)「参照渡し」という用語を「オブジェクト渡し」/「オブジェクト共有渡し」を意味するために使用しています。

(私の)好みの順序で変更を伝播する方法はいくつかあります。

  1. 新しい該当する値を返しますAC2 = doSomeTransformation(AC1)。これは一般的に最もきれいです。副作用や意外なコードを避けてください。必要に応じて、オブジェクト(または配列)にラップされている場合は、複数の値を返すことができます。

  2. クロージャーを使用します:doSomeTranformation(AC1, function (newValue) { AC2 = newValue })doSomeTransformationは次のようになります:function doSomeTransformation(_ac1, finished) { ...; finished(_ac1) }。私は通常、コールバックが関数自体の「コンテキストで実行される」場合、またはCPSスタイルでコードを記述する場合にのみこれを使用します。

  3. オブジェクトを変更します(結局のところ、ASは「オブジェクトの通過」です)。これは非常に厄介ですが、機能します。 var blah = {AC2: null}; doSomeTransformation(ac1, blah); ...; laterOn(blah.AC2)doSomeTransformationは次のようになりますfunction doSomeTransformation(_ac1, b) { ...; b.AC2 = _ac1; }。一般的にはお勧めしません。

ハッピーコーディング。


評価戦略からの該当する抜粋:

「参照による呼び出し」:(「参照による呼び出し」が誤って使用されているという私の主な議論は、それがすでに明確に定義された意味を持っているということです。ASやPythonなどの一部の言語で採用されている過負荷の用語は混乱を招くだけです)

参照による呼び出しの評価(参照によるパスとも呼ばれます)では、関数は、値のコピーではなく、引数として使用される変数への暗黙の参照を受け取ります。これは通常、関数が引数として使用される変数を変更できることを意味します。これは、呼び出し元に表示されます

「オブジェクトによる呼び出し」/「オブジェクト共有による呼び出し」:(ただし、これらの用語の不一致/ローカリゼーションを認める場合は注意が必要です。「参照による呼び出し」という用語は、これらのセマンティクスを意味するために誤用されることが多く、「値による呼び出し[参照の]"は、同じことを意味するためにいくつかのコンテキストで使用されます)

共有による呼び出しのセマンティクスは、関数内の関数引数への割り当てが(参照によるセマンティクスとは異なり)呼び出し元に表示されないという点で参照による呼び出しとは異なります。たとえば、変数が渡された場合、それは表示されません。呼び出し元のスコープ内のその変数の割り当てをシミュレートすることが可能です。ただし、関数は呼び出し元と同じオブジェクトにアクセスできるため(コピーは作成されません)、オブジェクトが変更可能である場合、関数内のそれらのオブジェクトへの変更は呼び出し元に表示されます。これは、呼び出し元とは異なるように見える場合があります。値のセマンティクス。

于 2011-05-07T05:56:05.987 に答える
3

ActionScriptの関数の引数は、参照ではなく値で渡されます。Javaと全く同じです。詳細はこちらをご覧ください。

于 2011-05-06T22:29:06.657 に答える
1

@Constantinerは正しい方向に進んでいると思いますが、彼の説明には詳細が欠けていると思います。ですから、もう少し詳しく説明しようと思います。最善の方法で私はそれを理解しています。私が間違っていれば、Yaは私を訂正することができます。

ドキュメントに記載されているように:

ActionScript 3.0では、すべての値がオブジェクトとして保存されるため、すべての引数は参照によって渡されます。ただし、Boolean、Number、int、uint、およびStringを含むプリミティブデータ型に属するオブジェクトには、値によって渡されたかのように動作させる特別な演算子があります。

したがって、ArrayCollectionは間違いなくオブジェクトであり、プリミティブ型ではないため、参照によって渡され、参照によって渡されたように動作する必要があります。しかし、ArrayCollectionへの参照変数は何ですか。概念的には、実際のコレクションデータを含むメモリスペースへのポインタにすぎません。これがいくつかのASCIIアートでの私の試みです:

                  |---|
 ac1(variable)--> |   | (ActualArrayCollection1)
                  |---|

                  |---|
 ac2(variable)--> |   | (ActualArrayCollection2)
                  |---|

繰り返しますが、ac1variableはメモリ空間へのポインタです。ac2variableは、いくつかの異なるメモリ空間へのポインタです。それらの1つを引数としてメソッドに渡すと、参照によって渡されます。したがって、メソッド内には、次のようなものがあります。

 ac1(variable)--> |---|
 ac1(argument)--> |   | (ActualArrayCollection1)
                  |---|

 ac2(variable)--> |---|
 ac2(argument)--> |   | (ActualArrayCollection2)
                  |---|

したがって、ac1variableとac1argumentの両方が同じメモリ空間を指します。それぞれに同じポインタ値が含まれているためです。ただし、ac1variableとac1argumentは、実際には異なるメモリスペースを保持しています。それらは同じではありません。

メソッドがこの行を実行するとき:

_ac2 = _ac1;

あなたはこのようなものを手に入れます:

 ac1(variable)--> |---|
 ac1(argument)--> |   | (ActualArrayCollection1)
 ac2(argument)--> |---|

 ac2(variable)--> |---|
                  |   | (ActualArrayCollection2)
                  |---|

メソッドの実行が終了すると、2つの引数はなくなり、元のポインター変数は変更されません。メソッド内でこのような直接割り当てを行う場合は、thisキーワードを使用してグローバル変数にアクセスできます。これはそれを行う必要があります:

   this._ac2 = _ac1;

もちろん、クラスレベルの変数にアクセスしている場合は、メソッド内のカプセル化の目的が損なわれる可能性があります。

コンパイラー設計の専門家とかそういうものが朝食にこれを食べて吐き出すと確信しています。私のASCIIアートが複数のブラウザ/マシン/OSなどで一貫していることを願っています。

于 2011-05-07T02:38:44.107 に答える
1

私が見ている問題は

var AC1.addItem(someObject);

関数内にアイテムを追加してみてください。

var AC1:ArrayCollection = new ArrayCollection;
var AC2:ArrayCollection = new ArrayCollection;

addItemToArrayCollection( AC1 );
setAC2(AC1,AC2);
// AC2 should be pointing to the ArrayCollection that AC1 is pointing to.

private function setAC2(_ac1:ArrayCollection, _ac2:ArrayCollection):void
{
   _ac2 = _ac1;
}

private function addItemToArrayCollection( arrayCollection:ArrayCollection ):void
{
  arrayCollection.addItem( someObject );
}

割り当ての後にブレークポイントを追加して、AC2がAC1と同じオブジェクトを持つ必要があることを確認できます。

于 2011-05-07T01:49:05.317 に答える