Instantiate a class from a string in ActionScript 3 - actionscript-3

I've got a string which, in run-time, contains the name of a class that I want to instantiate. How would I do that?
I read suggestions to use flash.utils.getDefinitionByName():
var myClass:Class = getDefinitionByName("package.className") as Class;
var myInstance:* = new myClass();
However, that gives me the following error:
[Fault] exception, information=ReferenceError: Error #1065: Variable className is not defined.

The easiest method I've come up with is to simply write the classnames out, separated by semicolons, anywhere in your project.
e.g. I create an Assets.as file with this in it:
package {
public class Assets {
// To avoid errors from the compiler when calling getDefinitionByName
// just list all of the classes that are not otherwise referenced in code:
Balloon;
Cloud;
FlyingHorse;
FlyingPig;
UFO;
Zeppelin;
}
}
Full code example/tutorial on this is here: http://producerism.com/blog/flashpunk-dame-and-lua-tutorial-part-6/

The other option is to use the mxmlc -includes compiler argument like this:
-includes=com.mydomain.package.MyClass
http://blogs.adobe.com/cantrell/archives/2010/09/loading-classes-dynamically-in-actionscript-3.html

Related

call constructors by using bracket syntax in AS3

As you know,you can access properties and methods in two ways:
dot syntax: object.property=value;
&
bracket syntax: object["property"]=value; or object["property"]=["value];
The bracket syntax also works for methods:
this["myMC"]["stop"]();
I tried to do that with constructors and i "Failed" :(
I try to make variables but
This code does NOT work:
this["mySprite"]=new ["Sprite"](); Error:Instantiation attempted on a non-constructor.
or
this["mySprite"]=new ["Sprite()"]; Error:Instantiation attempted on a non-constructor.
or
this["mySprite"]=["new Sprite"](); Error:Value is not a function.
or
this["mySprite"]=["new Sprite()"]; Error:a term is undefined and has no properties
None of them work
Maybe you wonder why i want that:
I want to make new variables at runtime:
this[tf1.text]=new [tf2.text]();
tf1.text is my variable's name and tf2.text is my constructor.
then I set properties and methods of my variable at runtime(you know how).
I appreciate helpful answers.
You can use getDefinitionByName() to get the class from a string, then create a new object from that class.
This is an example for getting the Sprite class from a string.
import flash.utils.getDefinitionByName;
var aClass:Class = getDefinitionByName("flash.display.Sprite") as Class;
var sprite:Sprite = new aClass();

Call to a possibly undefined method '' through a reference with static type Class

I made small .fla file in Flash Professional, and I have added .as (ActionScript File) in Flash Professional, and I have added something like code below to .as (ActionScript file), but the error appears and I am trying to figure it out, but can't, so I decided to post it in here instead.
package
{
import flash.display.MovieClip;
public class Bag extends MovieClip
{
static var firstBag:String;
public static function set setFirstBag(value:String):void
{
firstBag = value;
}
public static function get getFirstBag():String
{
return firstBag;
}
}
}
and I called it like this:
button1.addEventListener(MouseEvent.CLICK, onClickFirstButton);
function onClickFirstButton(e:MouseEvent):void
{
Bag.setFirstBag("First slot in the bag has been filled up!");
}
But I have received this following error:
Call to a possibly undefined method setFirstBag through a reference
with static type Class.
What could I do wrong?
The .as file and .fla file are on the same folder.
if I changed the Bag class to static. The error will be like this:
The static attribute may be used only on definitions inside a class.
Your answer much appreciated!
Thank you!
You're useing get like it is a mettod, but thay are accessors for properties so intead of:
Bag.setFirstBag("First slot in the bag has been filled up!");
use
Bag.setFirstBag ="First slot in the bag has been filled up!";
A few additional thoughts...
While syntactically valid, the definition and naming of your getter and setter is confusing and atypical, which I think contributed to your confusion about the behavior. You've actually defined two separate properties, one is write-only ("setFirstBag") and one is read-only ("getFirstBag"). Usually you define a getter/setter as the same property (ex "firstBag"), and without any "get" or "set" in the property name, since that is what the getter/setter is defining for you. Example:
private static var _firstBag:String;
public static function get firstBag():String {
return _firstBag:
}
public static function set firstBag(value:String):void {
_firstBag = value;
}
// usage
Bag.firstBag = "stuff";
trace(Bag.firstBag); // "stuff"
Also, you may very well have a good reason to use a getter/setter here, or you might just prefer it, but from the code you posted you could just define a public static var to do the same thing. (If you did, refactoring into a getter/setter if you needed some side-effect logic would be trivial, since the public API remains the same.)

How do one cast a instance of subclass to its superclass?

So I have this superclass grid class, and a subclass of the grid class named GrassTile1, GrassTile2, etc... all of the instance of the subclasses are stored in an array. How am I suppose to convert the instance of subclass to its superclass referencing to the array?
private var backgroundGrid = []; //the array which the grids are stored in, in the main class.
public class Grid extends MovieClip
{
protected var node :PathfindNode; //the variable I wish to access, from an instance of subclass.
public function Grid(){
node = new PathfindNode();
}
}
public class GrassTile1 extends Grid { //every subclass of Grid will extends Grid
public function GrassTile1() {
// constructor code
}
}
function getBackgroundGrid(i:int,j:int):Grid{ //in the main class
return Grid(backgroundGrid[i][j]); // this line gives me an error
}
TypeError: Error #1034: Type Coercion failed: cannot convert GrassTile1#2905d5f1 to Grid.
I've tried accessing backgroundGrid[i][j].node and other ways to work around that I could think of and failed. Any Idea?
Try :
return backgroundGrid[i][j] as Grid;
Personally, Grid seems like a bad class name to use. I think Tile makes more sense, as that GrassTile1 is not a grid as I logically understand a grid. A grid might contain a collection of tiles, so doesn't sound logical to use that as a class name for tiles.
Also, where is the line where you actually call the getBackgroundGrid method ? You should try casting there, as opposed to in that method. I believe that will solve the problem.
I can't verify the line throwing the error, so we are assuming that it's the return statement. But, it could be on the other side where you are calling getBackgroundGrid.
UPDATE : I have tried a .fla using what you are describing and it works just fine, I get no error. Which is why I'm thinking we are missing something here and maybe the definition of the class is not being used. Can you put a trace in your constructors to verify what you expect is actually happening ?

Dynamic Class Initiation AS3

I´m trying to initialize a class, based on a concatenation of a string and a number.
All my classes are public.
This is my code:
public function setCurrentPath(pathNumber:String)
{
var pth_class:Class = getDefinitionByName('Pth'+pathNumber) as Class;
var pth:MovieClip = new pth_class();
addChild(pth)
pth.getXY();
}
So I´m getting Error #1065.
Any help?
Yes I have up on my class file import flash.utils.*
Is your pth_class variable null?
If so, there are a couple of reasons this might be the case:
1) You haven't input the correct fully qualified class name of your class. E.g com.myClasses.Pth1
or
2)
If you're instanciating classes dynamically like this and there is no other "regular" reference to the class (such as blah = new Pth1()) then the "Pth1" class won't be included in the compilation process.
To get around this I think you can supply arguments to the compiler to force it to compile those classes OR you can manually include references to them in your existing code:
p1:Pth1;
p2:Pth2;

Can I create an instance of a class from AS3 just knowing his name?

Can I create an instance of a class from AS3 just knowing it's name? I mean string representation, like FlagFrance
Create instances of classes dynamically by name. To do this following code can be used:
//cc() is called upon creationComplete
private var forCompiler:FlagFrance; //REQUIRED! (but otherwise not used)
private function cc():void
{
var obj:Object = createInstance("flash.display.Sprite");
}
public function createInstance(className:String):Object
{
var myClass:Class = getDefinitionByName(className) as Class;
var instance:Object = new myClass();
return instance;
}
The docs for getDefinitionByName say:
"Returns a reference to the class object of the class specified by the name parameter."
The above code we needed to specify the return value as a Class? This is because getDefinitionByName can also return a Function (e.g. flash.utils.getTimer - a package level function that isn't in any class). As the return type can be either a Function or a Class the Flex team specified the return type to be Object and you are expected to perform a cast as necessary.
The above code closely mimics the example given in the docs, but in one way it is a bad example because everything will work fine for flash.display.Sprite, but try to do the same thing with a custom class and you will probably end up with the following error:
ReferenceError: Error #1065: Variable [name of your class] is not defined.
The reason for the error is that you must have a reference to your class in your code - e.g. you need to create a variable and specify it's type like so:
private var forCompiler:SomeClass;
Without doing this your class will not be compiled in to the .swf at compile time. The compiler only includes classes which are actually used (and not just imported). It does so in order to optimise the size of the .swf. So the need to declare a variable should not really be considered an oversight or bug, although it does feel hackish to declare a variable that you don't directly use.
Yes, use getDefinitionByName:
import flash.utils.getDefinitionByName;
var FlagFranceClass:Class = getDefinitionByName("FlagFrance");
var o:* = new FlagFranceClass();