views:

344

answers:

2

I have this small class called City that simply holds some information about a city, here it is:

class com.weatherwidget.City {
    var zipCode:String;
    var forecastText:Array = new Array(5);
}

When I have an array of cities and I change one of the forecastText of one city it will change that forecastText for all of the cities.

For example:

import com.weatherwidget.City;

var arr:Array = new Array();
arr.push(new City());
arr.push(new City());

arr[0].forecastText[0] = "Cloudy";
trace(arr[0].forecastText[0]);
trace(arr[1].forecastText[0]);

Will have the following output:

Cloudy
Cloudy

Even though I only changed arr[0].forecastText[0]. I think I must be misunderstanding something about arrays in objects for actionscript 2.

+1  A: 

The array needs to be initialized inside of a constructor for some reason or all the City objects will point to the same array. So the city class should look like:

class com.weatherwidget.City {
    var zipCode:String;
    var forecastIcons:Array;

    function City() {
     forecastIcons = new Array(5);
    }
}

I still don't know why it must be initialized in a constructor since the array isn't static, so if anyone would like to explain this that would be much appreciated.

Anton
+1  A: 

well the reason why ... hmmm ... little complicated to explain ...

alright ... ActionScript is prototype-oriented, as is ECMA-script ... classes are only a syntactic sugar introduced by actionscript 2 (this has changed yet again in as3, but that's a different subject) ...

so if this is the original code:

class com.weatherwidget.City {
    var zipCode:String;
    var forecastText:Array = new Array(5);
}

then this is, what actually happens:

//all classes get stuffed into _global, with packages being a property path:
if (_global.com == undefined) _global.com = {};
if (_global.com.weatherwidget == undefined) _global.com.weatherwidget = {};
//and the actual definition:
_global.com.weatherwidget.City = function () {};
_global.com.weatherwidget.City.prototype = { forecastText:new Array(5) }

the prototype object of City, that serves as prototype for instances of City, has a property called forecastText, which is an Array of length 5 ... so when looking up forecastText on an instance of City, it cannot be found directly and will be looked up in the prototype chain ... it will be found in the instance's prototype ... thus, all instances share the same Array ...

the difference is, that the second example gets translated to:

//same thing here:
if (_global.com == undefined) _global.com = {};
if (_global.com.weatherwidget == undefined) _global.com.weatherwidget = {};
//and the actual definition this time:
_global.com.weatherwidget.City = function () { this.forecastText = new Array(5); };
_global.com.weatherwidget.City.prototype = {}

as you might have noticed, declared members are only a compiletime thing ... if nothing is assigned to them, they simply will not exist at runtime ...

well, this explenation requires, that you either know JavaScript or ActionScript 1 a little, but i hope it helps ...

back2dos
I would never have discovered this thanks for the help :D
Anton
There is an excellent book called "Object-Oriented Programming with ActionScript" (http://tinyurl.com/m6s7bn) by Branden Hall (who also hangs out on StackOverflow) that explains all of this in very great detail.
Luke