tutorials flex enum_as3_instance_for_in
Enumeration using for..in on an instance of an as3 class
Article written 30/01/2007 22:03.
By Alcaraz Marc ( ekameleon ).
Overview
AS3 will be different by nature from Actionscript 1 and 2 : new virtual machine, based on new ECMAScript4 syntax, etc. All that remains now is to familiarise ourselves with the small differences and we can do this by coding with it :)
Today i’m going to talk to you about an interesting case that can crop up one day or another when we’re looking to use certain AS1/2 functions that don’t work at all in the same manner with AS3.
So we’ll see the difference between using the for..in command on an instance of an AS2 class and an instance of an AS3 class.
Example and demonstration
Let’s look straight away at little example in AS2 to illustrate enumerating instances of classes
1 - start with a small, basic AS2 class:
class test.User { public function User( name:String , age:Number ) { this.age = age ; this.name = name ; } public var age:Number ; public var name:String ; public function speak( msg:String ):Void { trace(this + " speak : " + msg) ; } public function toString():String { return "[User " + this.name + "]" ; } }
2 - In Flash 8 or MTASC i’m now going to try to instantiate an instance of this class and enumerate over the properties of this instance :
import test.User ; var u = new User("eka", 30) ; trace("my user : " + u) ; // my user : [User eka] for (var prop:String in u) { trace(prop + " : " + u[prop]) ; }
Which gives us this in the output window :
my user : [User eka] age :eka name : 30
We can see that the properites defined in the constructor of the class are enumerable even though the methods defined in the prototype are protected and don’t appear in the results of a for..in loop. So the public properties are enumerable but the methods are not (this would work in the same manner if i declared the properties but didn’t use the constructor to define their values)
Let’s now look at an AS3 version of the same example
1 - The test.User class with the necessary small modifications, which doesn’t really change anything with regards to the previous example
package test { public class User { /** * Creates a new User instance. */ public function User( name:String , age:int) { this.age = age ; this.name = name ; } public var age:int ; public var name:String ; public function speak( msg:String ):void { trace(this + " speak : " + msg) ; } public function toString():String { return "[User " + this.name + "]" ; } } }
2 – Here’s the main class for testing the instantiation and enumeration of this class.
package { import flash.display.Sprite; import test.User; public class TestDynamicEnum extends Sprite { /** * Creates a new TestDynamicEnum instance. */ public function TestDynamicEnum() { var u:User = new User("eka", 29) ; for ( var prop:String in u ) { trace( prop + " : " + u[prop] ) ; } } } }
Result… nothing in the output window ! But everything seems normal with this (It’s just with AS2 that there seems to be a problem). We can tell ourselves here that the object isn’t dynamic so there’s no reason why it should be enumerable. In this case i’ll try to modify the nature of the test.User class, making it dynamic.
It’s worth noting that looking in the Flex 2 documentation we can see a few lines of explanation on this subject, and if i’m not mistaken it says an enumeration with a for..in is only valid with a dynamic class.
package test { dynamic public class User { /** * Creates a new User instance. */ public function User( name:String , age:int) { this.age = age ; this.name = name ; } public var age:int ; public var name:String ; public function speak( msg:String ):void { trace(this + " speak : " + msg) ; } public function toString():String { return "[User " + this.name + "]" ; } } }
Result… still nothing in the output window :)
I’m now going to try to use the method setPropertyIsEnumerable() from the AS3 framework to transform one of the properties of my instance so that it appears in the for..in loop (in principle this should work by modifying the enumeration rights of a property in an object)
package { import flash.display.Sprite; import test.User; public class TestDynamicEnum extends Sprite { /** * Creates a new TestDynamicEnum instance. */ public function TestDynamicEnum() { var u:User = new User("eka", 29) ; u.setPropertyIsEnumerable("name", true) ; // name enumerable ? for ( var prop:String in u ) { trace( prop + " : " + u[prop] ) ; } } } }
Result… nothing again lol
Finally, i’ll try a last test (totally crazy or what ?) ! I’m going to code the test.User class like in AS1 by not declaring the properties (this shouldn’t cause a problem given that the class is dynamic)
package test { dynamic public class User { /** * Creates a new User instance. */ public function User( name:String , age:int) { this.age = age ; this.name = name ; } public function speak( msg:String ):void { trace(this + " speak : " + msg) ; } public function toString():String { return "[User " + this.name + "]" ; } } }
This time gives a positive result and the for..in works.
age : 29 name : eka
I’m now going to try to deactivate the enumeration on the name property on my instance to see if the method setPropertyIsEnumerable() works.
package { import flash.display.Sprite; import test.User; public class TestDynamicEnum extends Sprite { /** * Creates a new TestDynamicEnum instance. */ public function TestDynamicEnum() { var u:User = new User("eka", 29) ; u.setPropertyIsEnumerable("name", false) ; for ( var prop:String in u ) { trace( prop + " : " + u[prop] ) ; } } } }
All good, this time the method managed to modify the rights of a property of my instance and only the age property appears.
Conclusion
AS3 must consider that all properties, even public, must be protected in a class. I find that completely normal.
In AS2 and AS1 it was possible to use a non-documented function ASSetPropFlags to modify and secure properties.
Now the question is to understand if it’s possible to get around the protections imposed by AS3 and it’s compiler. I haven’t seen in AS3 a class or an equivalent method to the global ActionScript function ASSetPropFlags or the setAttributes that we find in SSAS or Javascript for example.
I really hope that Adobe have left in somewhere the tools to modify the rights of instances… if not, you must rely on the reflection API based on E4X from AS3 to enumerate the contents of the properties and methods of a class. I think this would be quite difficult from a first glance for a UnitTest framework for example ? But i could be mistaken, I lack experience in the implementation of such tools and it could be that code reflexion is preferable to enumeration.
Find out more
Author
By ALCARAZ Marc (aKa eKameleon) 2007. You can find this tutorial and comments on the subject on my blog.
Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42


