converting class name and passing to another class - actionscript-3

I have a function where I receive map as Class, everything works fine, but when I convert it to string, where map is something like 'IconNorth', convert it to "FieldNorth" and try to pass to another class constructor I get error.
public function newMap(map, x1:int, y1:int):void {
var createMap = new map();
list.push(createMap);
addChild(createMap);
var field = map.toString().split("Icon").join("Field");
new Board(this[field]);
}
and the Board class
public class Board extends MovieClip {
public static var list:Array = new Array();
public function Board(field=null) {
list.push(this);
if (field!=null) {
addChild(new field());
}
}
...
the error is
ReferenceError: Error #1069: Property [class FieldNorth] not found on Map and there is no default value.
I also tried 'getDefinitionByName' but it gives similar error.
So how do I convert a class name with or without using string to another class name and pass it to constructor?

First, you'll need to get the full class, so you can't just use CLass.toString() - in your case that would produce the string: "[class FieldNorth]"
Use getQualifiedClassName to get the full string class:
var classStr:String = flash.utils.getQualifiedClassName(map);
Then, to get the reverse, you'll have to use getDefinitionByName:
var myClass:Class = flash.utils.getDefinitionByName(classStr) as Class
var inst = new myClass();
So, for your example, this is what your code should look like:
public function newMap(map:Class, x1:int, y1:int):void {
var createMap:Object = new map();
list.push(createMap);
addChild(createMap);
var fieldClassStr:String = flash.utils.getQualifiedClassName(map).replace("Icon","Field");
try { //if getDefinitionByName fails, it will throw an exception, not return null
var field:Class = flash.utils.getDefinitionByName(fieldClassStr) as Class
new Board(field);
}catch(e:Error){}
}
public function Board(field:Class) {
list.push(this);
addChild(new field());
}

Related

Unable to clone vector with deep copy of objects

This is my vector that I want to fully clone (meaning that if I change the cloned vector it doesn't affect the original vector).
var vector:Vector.<Path_Tiles> = new Vector.<Path_Tiles>();
vector = path_finder.Find_Path(Gird.TILE_SET, start, end, R_G_B, SCAREDNESS);// return a vector of path_tiles in order
and I'm trying to put it into this vector
var vector2:Vector.<Path_Tiles> = clone(vector);
and clone method is this (which I found this method on a website so I do not fully understand it)
public function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
But I'm getting this error: "[Fault] exception, information=TypeError: Error #1034: Type Coercion failed: cannot convert AS3.vec::Vector.#85973d1 to AS3.vec.Vector.."
How do I convert Path_Tiles into an object?
Assure your Path_Tiles class has been registered:
flash.net.registerClassAlias("tld.domain.package.Path_Tiles", Path_Tiles);
Then, you may copy by serializing the data to a ByteArray:
var tiles:Vector.<Path_Tiles>;
var tilesCloned:Vector.<Path_Tiles>;
var byteArray = new ByteArray();
byteArray.writeObject(tiles);
byteArray.position = 0;
tilesCloned = byteArray.readObject() as Vector.<Path_Tiles>;
Cast the readObject() deserialization to Vector.<Path_Tiles> using the as keyword.
Constructors for objects serialized must accept default parameters.
To put this all together, say this was your Path_Tiles class:
Path_Tiles.as
package
{
public class Path_Tiles
{
public function Path_Tiles(property1:String=null, property2:int=undefined) {
this.property1 = property1;
this.property2 = property2;
}
public var property1:String;
public var property2:int;
}
}
Here is your main class, showing an example of deep cloning the Path_Tiles collection:
Main.as
package
{
import flash.display.Sprite;
import flash.net.registerClassAlias;
import flash.utils.ByteArray;
public class Main extends Sprite
{
public function Main() {
super();
var source:Vector.<Path_Tiles> = new <Path_Tiles>[
new Path_Tiles("Hello", 1),
new Path_Tiles("World", 2)
];
var cloned:Vector.<Path_Tiles> = clone(source);
}
public function clone(source:Vector.<Path_Tiles>):Vector.<Path_Tiles> {
flash.net.registerClassAlias("Path_Tiles", Path_Tiles);
var byteArray = new ByteArray();
byteArray.writeObject(source);
byteArray.position = 0;
return byteArray.readObject() as Vector.<Path_Tiles>;
}
}
}
Finally, we can see the object was deep copied; confirmed by memory address:

I can't seem to get a object to pull another variable object when the class is created?

I am trying to create two var one var is a object that gets another object inside the same class
package plus1
{
public class ScreenInfo
{
//setting a button to 0 means that it is disabled
public var object:Object = { button1:_Object2 };
public var _Object2:Object = { name:"test name" };
public function ScreenInfo()
{
}
}
}
but ever time i do this
var screens:ScreenInfo = new ScreenInfo();
var obj:Object = screens.object["button1"]
the object is null why is this shouldn't it pass me the second object?
Because you are using variable initializers, you can't safely use references to other members. How do you know that _Object2 exists when you create object ?
I suggest you move the instantiation of object in the constructor of your class :
public var object:Object;
public var _Object2:Object = { name:"test name" };
public function ScreenInfo(){
this.object = {button1:_Object2};
}

Problem with create object when know object's class name

I'm tring to create instance of class, when I got name of this class.
I think better to explain my problem will be this code:
package
{
import flash.utils.getDefinitionByName;
public class SomeClass extends ParentClass
{
[Embed(source='../assets/gfx/levelImg/level0.png')]
public static const Level0Img:Class;
public function someFunction():void
{
var imgString:String = "Level0Img";
var imgClass:Class = getDefinitionByName(imgString) as Class;
}
}
I invoke someFunction, and I get error: [Fault] exception, information=ReferenceError: Error #1065: Variable Level0Img was not defined.
What can be wrong with this ?
}
You are declaring a nested Class. The definition can't be found by the name you provided.
Try this:
(...)
public class SomeClass extends ParentClass
{
[Embed(source='../assets/gfx/levelImg/level0.png')]
public static const Level0Img:Class;
public function someFunction():void
{
var imgString:String = "SomeClass_Level0Img";
var imgClass:Class = getDefinitionByName(imgString) as Class;
}
(...)
why don't you just write var imgClass:Class = Level0Img;?That's better than classname guessing...

Can I treat a class as a object type?

I have a custom class say class A :
class A
{
public testA:int;
public testB:int;
}
Now, I have a object say Object C , the object has the exact same names of variables and everything as the class.
My question can I cast that object into class or vice versa. Instead of set/get of individual variables.
No you cannot cast an Object into a Class, but since a Class is an Object you can do the other way, but remember that accessing member from a Class is faster that accessing member from an Object.
To transform an Object into a Class you will have to instanciate the Class and then copy each Object field into that Class. But beware they will not be the same instance it's a copy.
To make the reverse you will have to use describeType on the Class to enumerate all the public field of that Class, and then copy the value into a new Object.
// simple sample:
class A {
public var testA:int;
public var testB:int;
}
function Object2A(o:Object):A {
var ret:A = new A();
for (var fieldName:String in o) {
if (ret.hasOwnProperty(fieldName)) {
ret[fieldName] = o[fieldName];
}
}
return ret;
}
import flash.utils.describeType;
function A2Object(a:A):Object {
var ret:Object = {};
var fields:XMLList=describeType(a).variable;
for each(var field:XML in fields) {
var fieldName:String=field.#name.toString();
ret[fieldName]=a[fieldName];
}
return ret;
}
var o:Object = {testA:12, testB:13};
var a:A = Object2A(o); // copy from object into class
o=A2Object(a); // copy from class into object
Unfortunately, no. The rules of duck-typing (if it looks like a duck and quacks like a duck, then it must be a duck) do not apply in AS3. Unless an object is explicitly constructed as type A, then a classification test will fail when compared to a generic object with the same properties. To cast generics into typed objects, I've always done this:
var obj = ((your generic object))
var a:A = new A();
for (var prop in obj) {
if (a.hasOwnProperty(prop)) a[prop] = obj[prop];
}

In ActionScript 3, tracing all properties of a value object

I have a number of value objects and I want to be able to create a function within it to trace out the properties and the values without specifying them directly. It will allow me to use the same code in all value objects as opposed to referring to variables within the value object. Ideally, I would like to replace the code in blogURLVars with this code.
Here's a sample value object
package items {
public class Blog {
private var _itemID:uint;
private var _blogTitle:String;
private var _blogText:String;
private var _blogCreated:String;
private var _blogCategory:String;
private var _blogFrontpage:Boolean;
public function Blog (itemID:uint,blogTitle:String,blogText:String,blogCategory:String,blogCreated:String,blogFrontpage:Boolean=false) {
_itemID = itemID;
_blogTitle = blogTitle;
_blogText = blogText;
_blogCreated = blogCreated;
_blogCategory = blogCategory;
_blogFrontpage = blogFrontpage;
}
public function get itemID():uint {
return _itemID;
}
public function get blogTitle():String {
return _blogTitle;
}
public function get blogText():String {
return _blogText;
}
public function get blogCategory():String {
return _blogCategory;
}
public function get blogCreated():String {
return _blogCreated;
}
public function get blogFrontpage():Boolean {
return _blogFrontpage;
}
public function toString():void {
}
public function blogURLVars():String {
var s:String;
s = "itemID="+ _itemID;
s += "blogTitle="+ _blogTitle;
s += "blogText="+ _blogText;
s += "blogCategory="+ _blogCategory;
s += "blogCreated="+ _blogCreated;
s += "blogFrontpage="+ _blogFrontpage;
return s;
}
}
}
DescrybeType could be of help here. I'm basing this answer in this other answer (you might want to check it out): Fastest way to get an Objects values in as3
Basically, the describeType function will let you inspect the public interface of your object. That means public variables, getter/setters and methods (plus some other info not relevant to your problem). So you get a list of all the getters and with that, return the names of said properties plus their actual values for a given object. Not that this is not exactly the same as your sample code, since this will not use the private variables, but rather will call the getters.
In code, this could be something like this (based on code in the linked question).
package {
import flash.net.URLVariables;
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
public class PropertiesHelper {
public function PropertiesHelper() {
}
private static var typePropertiesCache:Object = {};
public static function getPropertyNames(instance:Object):Array {
var className:String = getQualifiedClassName(instance);
if(typePropertiesCache[className]) {
return typePropertiesCache[className];
}
var typeDef:XML = describeType(instance);
trace(typeDef);
var props:Array = [];
for each(var prop:XML in typeDef.accessor.(#access == "readwrite" || #access == "readonly")) {
props.push(prop.#name);
}
return typePropertiesCache[className] = props;
}
public static function getNameValuePairs(instance:Object):URLVariables {
var props:Array = getPropertyNames(instance);
var vars:URLVariables = new URLVariables();
for each(var prop:String in props) {
vars[prop] = instance[prop];
}
return vars;
}
}
}
Use:
var blog:Blog = new Blog(1,"title&","text","cat","created");
var urlVars:URLVariables = PropertiesHelper.getNameValuePairs(blog);
trace(urlVars);
I'm using a URLVariables object since it seems that's what you want (though not actually what you blogURLVars method does), but you could change that in the getNameValuePairs method to suit your needs if necessary. An advantage of using a URLVariables object is that it handles the url-encoding for you automatically, so reserved characters such as &, =, etc, should not be a problem.