Explicit reference to actionscript class in top level package - actionscript-3

If you define a class in actionscript that has the same name as a class in the top level package (e.g. Array) there seems to be no way of explicitly referencing the class in the top level package.
UPDATE: This issue is only appearing in Flash Builder 4.7 with the new ASC 2.0 compiler, using Flash Builder 4.6 with an 'old' Flex SDK it works.
Example:
package
{
import flash.display.Sprite;
import mypackage.Array;
public class AS3Problem extends Sprite
{
public function AS3Problem()
{
var myOwnArray:mypackage.Array = new mypackage.Array();
// The line below will cause a compile error
// 'Ambiguous reference to Array'
var flashArray:Array = new Array();
}
}
}
I know the simple solution to this problem is to not create classes with a name that is the same as an as3 top level package class/function, but I'm intrigued as to how this could be 'fixed' in some way by explicitly referring to this package or some other means.
For those interested, I happened to accidentally import 'Array' from hamcrest-as3 while writing tests which caused a problem like this.

Try removing this line
import mypackage.Array;
so you do not import this custom Array and you always use the fully qualified name, I did not tested it but this should fix it.
EDIT:
I tested this and yes you have to add this import line, it will not work , but I can't reproduce the error, I can use and custom Array and the global Array fine with no issue/error or warrning.
EDIT2:
This also worked for me, can you test this too?
var globalArray:Class=(getDefinitionByName('Array') as Class);
var arr2:*=new globalArray();
arr2.push("test");
trace(arr2);

Related

AS3 Access of undefined property error

I have code that reads a JSON file to import the information about a level in a game I'm making. The code was running and compiling fine until suddenly every time I tried to build, FlashDevelop started erroring "build failed" without actually giving an error.
I ran the code through the mxmlc compiler, to give me an error message, and it returned an error saying "Error: access of undefined property JSON" in line:
var level:Object = JSON.decode(json);
This is confusing because the JSON library is clearly included at the top of the file, "import com.adobe.serialization.json.JSON;", and this error started occurring completely on it's own, which is odd...
package
{
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import net.flashpunk.Entity;
import com.adobe.serialization.json.JSON;
public class LevelParser
{
public static function GetLevelByID(ID:int, source:Class):Level
{
// Store new entity
var populated:Vector.<Entity> = new Vector.<Entity>();
// Parse file into string
var bytes:ByteArray = new source();
var json:String = bytes.readUTFBytes(bytes.length);
var level:Object = JSON.decode(json);
// Find correct level
...
EDIT: Strangely if I comment out the line to call it, and this function, the code compiled fine in mxmlc, but in Flashdevelop is says "Build Failed" with no error
This is actually a reference error.
As of AS3 SDK 4.5, JSON became a native class within the SDK. In previous versions, you would have to download the adobe serialize classes to access JSON - which may be your issue.
When using the mxmlc, it will compile with all the included libraries specified in your sdk flex-config.xml. In FlashDevelop, it will only use the classes you include.
Solution: add the adobe serialize class to your project

Custom AS3 Class not Updating

I've had a similar issue to this, but the means that I solved the last one are not working here.
I have a custom class that consists of 12 separate .as modules. They're declared in the document class as follows:
import trailcrest.v1.s3.averta;
import trailcrest.v1.s3.chronos;
import trailcrest.v1.s3.eripio;
import trailcrest.v1.s3.fabrilla;
import trailcrest.v1.s3.gradua;
import trailcrest.v1.s3.lingua;
import trailcrest.v1.s3.navigare;
import trailcrest.v1.s3.pedem;
import trailcrest.v1.s3.praeferre;
import trailcrest.v1.s3.scriba;
import trailcrest.v1.s3.securos;
import trailcrest.v1.s3.sonus;
public static var Averta:averta = new averta();
public static var Chronos:chronos = new chronos();
public static var Eripio:eripio = new eripio();
public static var Fabrilla:fabrilla = new fabrilla();
public static var Gradua:gradua = new gradua();
public static var Lingua:lingua = new lingua();
public static var Navigare:navigare = new navigare();
public static var Pedem:pedem = new pedem();
public static var Praeferre:praeferre = new praeferre();
public static var Scriba:scriba = new scriba();
public static var Securos:securos = new securos();
public static var Sonus:sonus = new sonus();
This is a new version of the code. I am able to successfully refer to all of these classes and the public variables and functions inside in the "osr.as" document class. I can also SEE one module from another (i.e. Sonus can see Scriba using "osr.Scriba."
Where I'm having trouble is that, while the various modules used to be able to access all of each other's public functions and variables perfectly, after I added some new modules and variables and removed some old ones, Flash Professional is still literally USING the old version. Inside of any module, the code hints are showing all of the old public functions and variables, and none of the new ones.
I am guessing that this has something to do with some sort of temporary file that I can't get to. I absolutely need this working this week!
My .fla is "Tester.fla," and the document class is "osr.as." They're both in the same directory. Also in the same directory is the folder structure "/trailcrest/v1/s3/" which contains all of the Trailcrest modules.
Help??
EDIT: Whenever I try to reference one Trailcrest class from another Trailcrest class (i.e. osr.Sonus.foo), I get...
TypeError: Error #1009: Cannot access a property or method of a null
object reference.
I have confirmed beyond a shadow of a doubt all references.
This is the age old problem of what ultimately boils down to is the Verify Error. It happens when you embed "Class A" in one or more applications, modules, swfs, etc. Ultimately every output swf that uses "Class A" must be recompiled when "Class A" is changed. Otherwise you end up with a situation where 1 module has the newer implementation but others don't. This problem is compounded by the fact that the application domain is defined as a "first in wins" when it encounters a Class of the same name / package - meaning if the old one is referenced first, the newer one loaded later gets ignored.
The more permanent solution is to use class promotion to an RSL that ultimately allows the RSL to control the actual "Class A" reference in which it also implements an "IClassAImpl" interface that all modules use. This allows the compiler to cross link the reference with a signature it knows about without actually embedding the actual class itself.
Well, I finally figured it out. Here's the skinny on what was happening:
#1: Flash was apparently pulling an old version of the Trailcrest modules. To remedy this, I backed up everything and then removed all old instances of Trailcrest from my entire computer. Then, I put only the new modules back. That fixed the problem with Code Hints showing the old modules and variables.
#2: I had been experiencing Error #1009 whenever one Trailcrest class tried to access any component of another Trailcrest class, even though the references were all correct.
The cause was that I was calling functions on the various modules directly from the document class osr.as, outside of a function. This, of course, executes on the program start.
However, all the code within one Trailcrest class that called another Trailcrest class (i.e. osr.Sonus.foo) would not be able to access "foo" because osr.as for some reason or another hadn't finished initializing the classes before it ran the code that called them. This occurred, even though the problem code was well below the code that initialized the classes (see my question).
To fix this, I simply had to wrap the problem code into a public static function in the document class, and then call it from the Timeline. That ensured that all the classes were initialized before they tried referencing each other.
Needless to say, everything is running like a well-oiled machine now. How weird.
I'd welcome any explanation as to WHY this fixed the problem.

Flash 11.2 sdk definition of base class Sprite was not found

I'm trying to build a simple sample project using FlashDevelop using Flash 11.2. For some reason it wont let me extend Sprite. When I try to compile it just says:
col: 31 Error: The definition of base class Sprite was not found.
All I have in my code is:
public class Game extends Sprite
{
}
Make sure that you have the following setup in your Flex SDK installation correctly:
\frameworks\libs\player\11.2\playerglobal.swc
and that you have a compiler constant called "swf-version=15" set in FD.
If that doesn't solve it, you have an ambiguous path to your libs. May they have spaces or special characters in them.
Did you import the right package? flash.display.Sprite
You put starling-framework as a tag so if you're using Starling it should be:
import starling.display.Sprite;

I get error when importing fxg into flex 4.6 project

I made an fxg file using Inkscape and the fxg plugin. It is called BugattiVeyron.fxg
I also created AS3 project using flex sdk 4.6 and FlashDevelop 4 and import this file using the import statement like this
import BugattiVeyron;
and instantiate it like this
private var bugatti:BugattiVeyron = new BugattiVeyron ();
Using the build button in FD4 does not give any errors, but when i run it I get this error although when I dismiss all the errors the file is beign imported well and I can add events to it.
the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::updateCallbacks()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:7345]
at mx.core::UIComponent/set nestLevel()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:4189]
at spark.core::SpriteVisualElement/http://www.adobe.com/2006/flex/mx/internal::addingChild()[E:\dev\4.y\frameworks\projects\spark\src\spark\core\SpriteVisualElement.as:2247]
at spark.core::SpriteVisualElement/addChild()[E:\dev\4.y\frameworks\projects\spark\src\spark\core\SpriteVisualElement.as:2211]
at resources::BugattiVeyron_Text_2126220941/createText()
at resources::BugattiVeyron_Text_2126220941()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at mx.core::FlexSprite()[E:\dev\4.y\frameworks\projects\framework\src\mx\core\FlexSprite.as:61]
at spark.core::SpriteVisualElement()[E:\dev\4.y\frameworks\projects\spark\src\spark\core\SpriteVisualElement.as:88]
at resources::BugattiVeyron()[resources\BugattiVeyron-generated.as:10]
so i get this error but the file is imported after I dismiss the errors.
what could be the problem, any idea?
I struggled with this issue myself and finally figured out how to get it working. There are two ways.
Your FXG file needs to be in the same directory as your Main.as in order to call it like this:
import BugattiVeyron;
But or course if you have your image assets in another folder you will have to set a class path in your project in order to reference the FXG file. Obviously we can't access the FXG file in another directory like this:
import ../lib/BugattiVeyron
If you right click on your project in FlashDevelop and click on Properties from the context menu you will be able to add your directory of choice as a classpath in order to access your FXG file. In my case I added lib as a classpath for the project. This enabled me to import my asset like you previously tried doing.
import BugattiVeyron;
public class Main extends Sprite {
var bugatti:BugattiVeyron = new BugattiVeyron();
..some code here...
}
Hope this helps, I struggled for a week trying to figure this out.
I ran into the same problem, specifically when trying to instantiate an FXG that contained text (a <RichText> element) from an AS3-only project (no MXML) in FlashDevelop. I was able to import and use other FXG files that didn't contain RichText without any trouble.
I'm a little hazy on the exact details, but it seems that the error occurs as a consequence of the call to createText() (resources::BugattiVeyron_Text_2126220941/createText() in your case) because the Flex library isn't initialized for a pure AS3 application. The simplest solution is to define the application in MXML rather than AS3, i.e.
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:bv="*"
>
<bv:BugattiVeyron/>
</s:Application>
instead of
import BugattiVeyron;
public class Main extends Sprite {
var bugatti:BugattiVeyron = new BugattiVeyron();
}
(More on this in a related question: [Possible to use Flex Framework/Components without using MXML?. Look for the "necessary updates for Flex 4" section.)
Alternatively, if you don't want the runtime overhead of the Flex libraries, you can edit your FXG to convert the text to paths. This should work with AS3-only projects, but I wouldn't be too surprised if there were other FXG features that ran into similar problems.

AS3 OOP common practices examples?

I am trying to better understand the AS3 OOP structure and organization, but I am having some problems wrapping my head around it. I want to create multiple class files and it seems that best practice is not to and to put all classes in one file? I have searched for hours on the web and came up with little for good examples. Maybe seperate files is not the way to go while using AS3, but to me it only makes sense for modularzation. The files I have been playing with are:
Main.fla
Main.as (document class)
TestOne.as
TestTwo.as
TestThree.as
TestFour.as
TestFive.as
I have created a folder called classes to house all class files except the Main.as which resides with the FLA.
All five Test classes are the same code except the file name and class name.
Here is how I am importing the files:
Main.as
package classes
{
import flash.display.MovieClip;
import classes.TestOne;
import classes.TestTwo;
import classes.TestThree;
import classes.TestFour;
import classes.TestFive;
public class Init extends MovieClip
{
trace("This is Main Class");
var testOne : TestOne = new TestOne;
}
}
TestOne.as
package classes
{
import flash.display.MovieClip;
public class TestOne extends MovieClip
{
trace("This is TestOne");
public function testing():String
{
return "This is the testing method";
}
}
}
Are the above examples I created good AS3 OOP practices? I understand these are real basic classes, but I think it should get the point arossed.
I am using CS3
Might be good to look at the Flex SDK coding conventions and best practices. It is a point by point rundown of how you should be using ActionScript 3. There is quite a bit of OOP stuff scattered throughout, so take a good skim through it. I think it is worth any new or experienced AS3 devs to have a read, because there is a lot of useful information there.
OOP is a big subject but here is a good primer.
ActionScript 3 design patterns will be also useful for you.
As Nathan said, big subject.
The thing about having all classes in one file is related to the topic "visibility of a class" and "access modifiers".
The modifier is that what is written before the class keyword. It can be public or internal. Internal means, that only code that is placed in the same directory (package) of the internal class can create an object of it. Public means, any code can create an instance of the class. Random link via google: http://flexmaster.blog.co.in/2010/05/20/action-script-use-access-modifiers-with-classes-and-class-members/
You are allowed to have multiple classes in one file. But then only one can have the modifier public. All others need to be internal. If you leave out the modifier, a class is by default internally visible. An internal class in a multiple classes file can be accessed only from within this file.
There are two more modifiers: protected and private. Both are applicable only to properties or methods. As an advanced developer you can even define you own modifier by using namespaces.
The rules of OOP still apply to AS3
1) Encapsulation.
2) Inheritance.
3) Abstraction.
4) Polymorphism.
Apply them or not is your choice but it is good practice.
And don't forget the most important rule "KISS" (keep it simple stupid)
I also want to point out your code has an error
package classes
{
import flash.display.MovieClip;
public class TestOne extends MovieClip
{
trace("This is TestOne");// this line is not inside a function and will most undoubtly error out your app.
public function testing():String
{
return "This is the testing method";
}
}
}
I think you either did something wrong when you copied the code into SO or you're not placing the trace statements correctly. You need to place the trace("This is TestOne"); inside a constructor in TestOne.as, like this:
public function TestOne() {
trace("This is TestOne");
}
The same goes for the code inside the Init class, which now reads:
trace("This is Main Class");
var testOne : TestOne = new TestOne;
but should be(note the bracers after new TestOne):
public function Init() {
trace("This is Main Class");
var testOne : TestOne = new TestOne();
}
What happens when you run your SWF, is that the constructor of the class Init will:
1) Trace "This is Main Class" to your console.
2) It will construct a new object(thus the name constructor) by calling the constructor of the class TestOne.
If you were to add this line to the end of the constructor in the class Init:
testOne.testing();
you should see this in the console: "This is the testing method".
If you would now comment out the line: var testOne : TestOne = new TestOne(); and run the SWF again, you'll get an error telling you something is null. This is because you attempt to call the method testing on an object that does not exist.
I do realize this is primarily fixing some coding errors of yours, and not so much helping you understand OOP. But hopefully you can pick up some help regarding object construction. I see some answers already mention key OOP principle that you really should look into.
Edit:
Remember that duplicating code is never a good thing, so if you find that all of the classes TestOne - TestFive contain the same code, except for some minor detail. You should probably change them into one class.
In your case you could for example change TestOne so that the constructor accepts a String, and then in your testing function you could just trace that String. By changing your TestOne class into the following you effectively get rid of 4 other classes. You also encapsulate a String inside of the class TestOne.
package classes {
import flash.display.MovieClip;
public class TestOne extends MovieClip {
private var message : String;
public function TestOne(myMessage:String) {
message = myMessage;
trace("This is TestOne");
}
public function testing() : String {
return message;
}
}
}