ActionScript 3 - Value Reference

I thought I had links in AS3, but the following behavior puzzled me:

// declarations for named individual reference later on var myAmbientSound:Sound; var myAmbientSoundLocation:String = "http://ambient_sound_location"; var myPeriodicSound:Sound; var myPeriodicSoundLocation:String = "http://periodic_sound_location"; var myOccasionalSound:Sound; var myOccasionalSoundLocation:String = "http://occasional_sound_location"; // for iterating through initialization routines var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound]; var mySoundLocation:Array = [myAmbientSoundLocation, myPeriodicSoundLocation, myOccasionalSoundLocation]; // iterate through the array and initialize for(var i:int = 0; i < mySoundArray.length; i++) { mySoundArray[i] = new Sound(); mySoundArray[i].load(new URLRequest(mySoundLocation[i])); } 

At this point, I think that mySoundArray[0] will refer to the same object as myAmbientSound ; however, access to myAmbientSound raises a null pointer exception, and mySoundArray[0] works as expected and references the Sound object. What i don't understand here?

+4
source share
4 answers

This is more like Java reference variables than C pointers.

 var myAmbientSound:Sound; var myPeriodicSound:Sound; var myOccasionalSound:Sound; //these variables are not initialized and hence contain null values 

Now you create an array containing the current (null) values ​​of these variables

 var mySoundArray:Array = [myAmbientSound, myPeriodicSound, myOccasionalSound]; 

Now the array contains three zeros [null, null, null] , and not three pointers to the Sound objects that you expect from it.

Now when you call mySoundArray[0] = new Sound(); , a new Sound object is created and its address is assigned to the first location of the array - it does not change the variable myAmbientSound .

+7
source

Since others are in no hurry to come up with very good explanations, I will instead try to answer questions that you ask implicitly:

At this point, I think mySoundArray[0] will reference the same object as myAmbientSound

But myAmbiendSound does not reference anything. From your code:

 var myAmbientSound:Sound; 

The above simply creates a local variable of type Sound, a potential reference. A β€œfinger,” which may indicate something, in a simple environment. All local variables are references. And by the way, not all links are local variables, the properties of the object are also links, as well as Array and Vector elements. In any case, the expression above does not create an object of class Sound . It simply declares a local variable that can refer to an object of the Sound class. When declared, it has the special value undefined .

There is a difference between declaring a variable as described above and assigning it a value. The new operator creates an object and returns a reference to it. The assignment operator = leads to what is on the left side, everything on the right is rude.

One way to have a local variable above an object reference:

 myAmbientSound = new Sound(); 

In your case, as I said, the variable myAmbientSound has the special value undefined , since you just declared it and it has not yet been assigned a value. In addition, as we see from the code, it does not refer to anything during the entire execution time of your code fragment.

Now, before I explain that you are inserting a string into your array:

  var mySoundArray:Array = [ myAmbientSound, ... 

you must remember that the elements of the array, as well as the properties of the object, are also references. mySoundArray[0] can refer to an object, as can mySoundArray[1] , etc.

The line of code above declares a new local variable and makes a reference to a new array object. Declaration and definition in one statement.

Now, since we have established that your local variable myAmbiendSound contains the special value undefined , your first element of the array ends with a reference to the same value - undefined , initially . In the loop later, you have the first element (or, if we want to be hypocritical, the element in the number that the i variable refers to) refers to the new Sound object. At this moment (and for the entire area of ​​your fragment, as we noticed), since myAmbiendSound is undefined , comparison of the two for equality does not work - they do not refer to the same object, nor the objects to which they refer are considered "equal "(how = works in AS3 - this is another topic) - the first is undefined , and the latter points to a Sound object.

In addition, a minor correction: "access" to the object does not result in an exception at runtime. An attempt to access a property (using the dotted notation syntax) of a link that does not point to an object - however, raises an exception at run time. As if you were writing trace(null.foo) - null not an object and certainly does not have a property named foo . The same goes for undefined .

By the way, null == undefined is true , but null === undefined is false . Just saying it. In rare cases (depending, of course) you will have to observe this detail.

Hope this clarifies the issue. I consider this an addition to all that was said earlier here.

+3
source

In general, links in ActionScript, Java, and other languages ​​are not considered links in C / C ++. If the links worked like in C / C ++, the code you wrote would be correct and worked as you expected. In general, you should try to think of links as pointers with automatic dereferencing. Your code is a great example of the difference between C / C ++ links and modern links.

Here is an example of the consequences of this behavior that applies to the garbage collector:

 var someRef:Sound = new Sound(); someRef = null; 

Then, the Sound object that I created on the first line still exists and can continue to exist. This is important to remember, because if you register event listeners in AS3, you create an additional link to them to prevent them from being destroyed by the GC. That's why you should almost always use the full call to AddEventListener, forcing it to use weak references (which are not taken into account for the GC).

Also, keep in mind that all function calls are ByVal in AS3. So this code will not work:

 function initSound(a:Sound, b:String):void { a = new Sound(); a.load(new URLRequest(b); } var myAmbientSound:Sound; var myAmbientSoundLocation:String = "http://ambient_sound_location"; initSound(myAmbientSound, myAmbientSoundLocation); 

The good news is that most languages ​​with built-in garbage collection have the same behavior for links, so as soon as you hang them up, you can pick up those languages ​​faster.

+2
source

A variable definition does not create a pointer.

 // This line is only creating a QName, but no pointer. // Value of "myAmbientSound" is "null". var myAmbientSound : Sound; // Here, you put the reference pointed by myAmbientSound into the array. // It is null, so mySoundArray[0] will also be null. var mySoundArray : Array = [myAmbientSound]; // Here, you assign a new pointer to the index 0 of mySoundArray. // It is simply overwriting the "null" value, but there is no // connection to myAmbientSound. mySoundArray[0] = new Sound(); // myAmbientSound is still null, as it is still pointing to nothing. trace(myAmbientSound); // null // But index 0 of mySoundArray holds a pointer to the sound you instanciated. trace(mySoundArray[0]); // [Object Sound] 

In order to achieve what you are looking for, you should do something like this:

 // Creating the variable and pointing it to an object instance. var myAmbientSound : Sound = new Sound(); // Here, the pointer isn't null, so the reference can be added to the array. var mySoundArray : Array = [myAmbientSound]; // And now, both accessors points to the same object instance. trace(myAmbientSound); // [Object Sound] trace(mySoundArray[0]); // [Object Sound] 
+1
source

Source: https://habr.com/ru/post/1301580/


All Articles