10
votes

ArrayCollection est transmis en fonction de la valeur au lieu de par référence à Flex 3

Je veux définir ArrayCollection # 2 = sur ArrayCollection n ° 1 via une fonction dans Flex 3. Je passe les deux collections de tableau à une fonction et définissez ArrayCollection # 2 = ArrayCollection n ° 1. Cependant, il semble ne pas être un arraycollection # 2 par référence car après l'appel de la fonction, le tableau n ° 2 n'a pas été modifié. Je crois comprendre que cela devrait être adopté par référence et travail, je fais quelque chose de mal? Ci-dessous le code:

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;
}


1 commentaires

+1 pour obtenir les termes corrects, par accident ou non. Voir Stratégie d'évaluation . Bien que "Pass par la valeur [de référence d'objet]" est mieux appelé "Pass par objet" ou "Pass par partage d'objets" pour éviter cette confusion. Je sais juste que quelqu'un va dire "mais ils sont passés par référence!" (Et cela peut avoir même conduit à la confusion actuelle si le terme a été mal utilisé dans une documentation ou un tutoriel ;-)


4 Réponses :


3
votes

Les arguments de la fonction dans la carte ActionScript par valeur, pas par référence. C'est absolument la même chose que dans Java. Vous pouvez lire dans les détails ici .


4 commentaires

Mais cela semble indiquer qu'il devrait être adopté par référence: Livedocs.adobe.com/flex/3/html/...


Ok, pour être précis, suivez mon lien et vous trouverez une description entièrement liée à ActionScript aussi: "Java passe les références par valeur Tout comme n'importe quel autre paramètre. Cela signifie que les références transmises à la méthode sont en réalité des copies des références originales. "


+1 C'est la seule bonne réponse jusqu'à présent. La documentation incorrectement utilise "Pass par référence" pour signifier "Pass par partage d'objets" (ou "Pass par la valeur [de la référence]" pour les personnes qui aiment lier les pointeurs). S'il vous plaît voir Stratégie d'évaluation . Le "problème" est l'affiche s'attend à ce que réel "passe par référence", qui n'est pas pris en charge dans JavaScript ou ActionScript.


(Mon terme "mal" est un TAD dur, cependant, je me tiens à l'affirmation selon laquelle l'utilisation du terme surchargé ne ajoute que de la confusion. L'affiche indique clairement à plusieurs reprises qu'il attendait de la réelle (ou Autre , si vous préférez) "Pass par référence" Sémantique.)



1
votes

Le problème que je vois est xxx

essayez d'ajouter l'élément dans une fonction. xxx

Vous pouvez ajouter un point d'arrêt après la mission et voir que AC2 devrait avoir le même objet que AC1.


1 commentaires

C'est complètement faux. AdditaltemtoArrayCollection (AC1); n'a rien à voir avec les références. L'utilisation de votre code AC1 a quelque partobject tandis que AC2 est vide, identique au code de l'auteur de sujet.



1
votes

Je crois que @Consantinner est sur la bonne voie, mais je pense que son explication manque de détails; Donc, je vais essayer d'expliquer avec un peu plus de profondeur; au mieux que je comprends bien. Tu peux me corriger si je me trompe.

Comme indiqué dans les docs :

Dans ActionScript 3.0, tous les arguments sont passé par référence, parce que tout Les valeurs sont stockées comme objets. Cependant, objets qui appartiennent à la primitive Types de données, qui comprend Boolean, Nombre, int, uint et chaîne, ont opérateurs spéciaux qui les font se comporter comme s'ils étaient passés par valeur.

Donc, une arraycollection est définitivement un objet, et non un type primitif, il convient de transmettre par référence et agir comme il a été adopté par référence. Mais quelle est votre variable de référence à l'arraycollection. Conceptuellement, il suffit d'un pointeur sur un espace mémoire contenant les données de collecte réelles. Voici ma tentative de l'art ASCII: xxx

à répéter, ac1variable est un pointeur sur un espace mémoire. AC2Variable est un pointeur à un espace mémoire différent. Lorsque vous passez l'un d'entre eux dans une méthode comme argument, il est transmis par référence. Donc, à l'intérieur de la méthode, vous avez quelque chose comme ceci: xxx

donc à la fois ac1variable et ac1argument point dans le même espace mémoire; parce qu'ils contiennent chacun la même valeur de pointeur. Cependant, AC1Variable et AC1ARGUMENT détiennent réellement différents espaces de mémoire. Ils ne sont pas les mêmes.

Lorsque la méthode exécute cette ligne: xxx

Vous obtenez quelque chose comme ceci: xxx

Lorsque l'exécution de la méthode se termine, les deux arguments disparaissent et les variables de pointeur d'origine restent inchangées. Si vous souhaitez effectuer une affectation directe comme celle-ci à l'intérieur d'une méthode, vous pouvez accéder à la variable globale à l'aide du ce mot clé. Cela devrait le faire: xxx

bien sûr, qui peut vaincre le but de l'encapsulation à l'intérieur d'une méthode si vous accédez à des variables de niveau de classe.

Je suis sûr qu'un expert sur la conception du compilateur et de telles choses vont manger pour le petit-déjeuner et la crachera. J'espère que mon art ASCII est cohérent sur plusieurs navigateurs / machines / OSES / etc ..


5 commentaires

La documentation est erronée - il utilise de manière incorrecte "Pass par référence" (de même que la documentation Python) pour signifier "Pass par partage d'objets" et il se trouve le noeud de ce "dilemme". Ainsi, alors que ce message explique "Pass par partage d'objets", il ne traite pas de la question des affiches :-) L'affiche s'attendait à "passer par référence" (avec la bonne signification) pour permettre la modification de la variable transmis, selon C # 'S out / ref ou VB'S BYREF ou C ++' S (Référence) & .


Le truc est un peu intéressant, mais il convient de noter que cela ne fonctionnera que si la méthode s'ils sont invoqués sur l'objet global (ou explicitement sur l'objet pour lequel AC2 est invoqué. Un membre - je pense this.ac2 = _ac1 montre plus de l'intention; le désir est de modifier ac2 (bien que via le paramètre local _ac2 >))


@pst basé sur le code de l'affiche d'origine; Je n'ai aucune raison de croire que la méthode AC2 et la variable AC2 ne font pas partie de la même classe; mais oui pour la référence "Cette" référence au fonctionnement de la méthode doit être dans la classe qui contient la variable AC2.


@pst je vais admettre que c'est la première fois que j'ai entendu le terme "passe par le partage d'objets". Comme indiqué dans l'article Wikipeida: "Le terme" appel "par partage" n'est pas en usage courant; la terminologie est incompatible entre différentes sources. " Avez-vous une référence pour les affirmations selon lesquelles la documentation est fausse?


"Faux" est un peu dur et utilisé comme hyperbole ici; Ma réponse contient plus de détails. Je suis sur une quête d'éradiquer cette utilisation de "Pass par référence" comme en jeu, il n'y a aucun moyen de décrire le réel "passe par référence". En outre, je trouve "passe par référence" (dans ce contexte) et "Pass par la valeur [de la référence]" pour être des termes de faible niveau (pourquoi devrais-je me soucier de la mise en œuvre?) Lorsque la sémantique précise correspond à un plus apte terme. Vous êtes absolument correct sur la terminologie incompatible, mais je pense que l'utilisation augmente - j'essaie, dammit ;-)



6
votes

S'il vous plaît voir Stratégie d'évaluation .

comme utilise "passe par objet" / "Pass par partage d'objets" . C'est-à-dire que "l'objet" est passé (pas une copie, un clone ou dupliquer) et toute modification à l'objet sont partagées .

Cependant, l'affectation _ac2 = _ac1 ne modifie que la valeur de la variable de paramètre [locale de la fonction] et n'aura aucune incidence sur aucune variables pendant l'invocation de la fonction. La seule chose transmise est les valeurs ("objets") qui résultent de l'évaluation des variables (ou de toute expression arbitraire) utilisée dans l'invocation de la fonction.

C'est parce que, comme indiqué ci-dessus, la stratégie utilisée est "Passer par objet" et non (car la documentation indique "Pass par référence", ce qui signifie vraiment "de la valeur" la référence] "ou juste ..." passe par objet "). C'est-à-dire le terme "passe par référence" est en fait mal utilisé et donc, confusant . (Il est mal utilisé dans un certain nombre de langues et de documentation. C'est une bataille en montée qui tente d'arriver à une signification commune.)

Si cela était vraiment "passe par référence" puis attribuant une nouvelle valeur à _ac2 se propagerait. (Avant de poser un commentaire disant comment «passer par référence», veuillez consulter le lien en haut et considérez que «Pass par référence» couvre le cas de C # 'S OUT / REF , VB' CODE> BYREF , TSQL'S SORTIE ET C ++ 'S (Référence) & - Ces notions ne sont pas en tant que, JavaScript ou Java). Cependant, comme indiqué correctement dans le poste d'origine (et une réponse de soi supplémentaire), ce n'est pas le cas - Conclusion: Comme il ne supporte pas «Pass par référence»; en outre, la documentation (confusion) utilise le terme "passe par référence" pour signifier "Pass par objet" / "Pass par partage d'objets".

Il y a plusieurs façons que le changement puisse se propager, commandé par ordre de (ma) préférence:

  1. renvoie la nouvelle valeur applicable: AC2 = Dosometransformation (AC1) . C'est généralement le plus propre. Évitez les effets secondaires et le code surprenant. Les valeurs multiples peuvent être renvoyées si elles sont enveloppées dans un objet (ou une matrice) selon le cas.

  2. Utilisez une fermeture: dosométranformation (AC1, fonction (newvalue) {ac2 = newvalue}) où la dosométransformation peut ressembler à: de la dosométransformation (_ac1, fini) {.. .; fini (_ac1)} . Je n'utilise généralement que cela lorsque le rappel "fonctionne dans le contexte" de la fonction elle-même ou lorsque vous écrivez le code dans un style CPS.

  3. Mutate Un objet (comme c'est "Passer par objet", après tout). c'est très icky, mais cela fonctionnera. var bla = {ac2: null}; Dosométransformation (AC1, BLAH); ...; latéron (bla.ac2) où la dosométransformation peut sembler ressembler à une dosométransformation fonction (_ac1, b) {...; B.AC2 = _AC1; } . Non recommandé en général.

    codage heureux.


    Extraits applicables, de stratégie d'évaluation :

    "appeler par référence": (mon argument principal pour "appeler par référence" étant utilisé incorrectement est qu'il a déjà une signification bien définie; le terme surchargé adopté par certaines langues telles que et python ajoute simplement une confusion)

    Dans l'évaluation par appel de référence (également appelée passage à la référence), une fonction reçoit une référence implicite à une variable utilisée comme argument, plutôt qu'une copie de sa valeur. Cela signifie généralement que la fonction peut modifier la variable utilisée comme argument - quelque chose qui sera vu par son appelant .

    "appeler par objet" / "appeler par partage d'objets": (mais payez-vous là où il reconnaît l'incohérence / la localisation de ces termes; le terme "appel par référence" est souvent mal utilisé Pour impliquer ces sémantiques et "appeler la valeur [de la référence]" est utilisé dans certains contextes pour signifier également la même chose)

    La sémantique du partage d'appel diffère de l'appel-référence en ce sens que les arguments de fonction dans la fonction ne sont pas visibles pour l'appelant (contrairement à la sémantique par référence), donc par exemple. Si une variable a été transmise, Il n'est pas possible de simuler une affectation sur cette variable de la portée de l'appelant . Cependant, étant donné que la fonction a accès au même objet que l'appelant (aucune copie n'est effectuée), des mutations à ces objets, si les objets sont mutables, dans la fonction sont visibles à l'appelant, ce qui peut sembler différer de l'appel Value Semantitique.


0 commentaires