Passing variables between classes in Actionscript 3 - actionscript-3

I'm not terribly good at this modern object coding lark and think I may have misunderstood how this is meant to to work:
This is test.as in my Flash Builder 4.7 project called test
package
{
import flash.display.Sprite;
public class test extends Sprite
{
public var myVar:int = 10;
public function test() {
var myTestsub:testsub = new testsub;
}
}
}
And this is my testsub.as file:
package
{
public class testsub
{
public function testsub()
{
trace(myVar);
}
}
}
Flash Builder tells me that in testsub.as "Possible access of undefined variable myVar" and will not compile.
From my limited, and probably incorrect, understanding, making myVar public in test.as should allow testsub.as to use it. Can anyone explain where I am going wrong? Thank you in advance.

you need to wirte your var like this:
public class the_var
{
public function the_var
{
public static var my_var:number = 10;
}
}
and call your var in other classes like this:
public class the_test
{
public function the_test
{
trace(the_var.my_var);
}
}

There are no connections between the classes. They need a link, similar to this solution:
public class test extends Sprite
{
public var myVar:int = 10;
public function test() {
var myTestsub:testsub = new testsub(this);
}
}
public class testsub
{
public function testsub(otherClass:test)
{
trace(otherClass.myVar);
}
}
In test when creating the testsub-class we pass a long a referende to the instance of test. That makes it possible to access public functions & variables on that instance from the other class. (Observer that you need to add test-class as an import inside testsub in order to compile code.

Related

AS3 undefined function #1006

I have a parent class called 'main.as'. I am trying to get the child class to call main's function. They both reside in the same folder.
// main.as //
package {
public class main extends MovieClip {
public function main() {
var child:child_mc = new child_mc(this);
}
public function callFunction():void {
trace("Done it");
}
}
}
.
// child.as //
package {
import main;
public class child extends MovieClip {
private var main:MovieClip = new MovieClip();
public function child(main:MovieClip):void {
this.main = main;
main.callFunction();
}
}
}
This is the error I've been getting:
TypeError: Error #1006: callFunction is not a function.
so I tried doing a trace like this
trace(main.callFunction);
and it says undefined. Can someone tell me what I am missing. I get this feeling its a very basic thing that I have overlooked!
Your "child" package is defined as "main". I'm not even sure how it complied, let alone run to the point of showing the error message you got.
I believe the code below should do what you expected.
(I also took the liberty to rename the classes to use CamelCase (with initial caps) to adhere to best practices and to be easier to distinguish from variable names.)
Main.as
package {
public class Main extends MovieClip {
public function Main() {
var child:ChildMC = new ChildMC();
child.main = this;
}
public function callFunction():void {
trace("Done it");
}
}
}
EDIT: I just saw your comment that points out that child_mc is a MovieClip in the Library. I guess then that the child class is set as the Base Class of the child_mc?
If so, you cannot pass properties through the instantiator, you need to find another way to pass along the instance of the Main class to the Child class.
One way would be to add a setter, like the following:
Child.as (Base Class for ChildMC)
package {
public class Child extends MovieClip {
private var _main:Main;
public function Child() {
}
public function set main(main:Main):void {
this._main = main;
this._main.callFunction();
}
}
}

Access of Undefined property? Actionscript 3

I was programming something and when I thought everything was nice and good, Flash throws an error to me!?
At first I was dumbstruck. Then after checking my code, I couldn't see the culprit. So what I did was 'simple it down', and changed it to just a trace statement.
I was still however getting the error. I don't know what is wrong.
package {
import flash.display.MovieClip;
import src.data.DActors;
public class DocumentClass extends MovieClip {
public var dActors:DActors = new DActors;
public function DocumentClass() {
trace (dActors);
trace ("Main");
}
}
}
This is the DActors Class:
package src.data
{
public class DActors
{
public var me:int = 1;
public function DActors();
{
trace(me);
}
}
}
Some scope I'm not aware of or something?
Oh, and by the way, it throws that ''me' is not defined'!?
EDIT: Actually, I failed to realize the real problem, why the hell is my constructor not accepting variables!
package src.data
{
public class DActors
{
public var actors:Array = new Array();
public var dActor:DActor = new DActor();
public function DActors();
{
actors.push(dActor);
}
}
}
outputs:
1120: Access of undefined property actors.
1120: Access of undefined property dActor.
???? This worries me greatly. Either my eyes are fooling me or I'm missing something very basic.
public function DActors();
Constructor function will not end with ;(semicolon).
public var dActors:DActors = new DActors;
Should be:
public var dActors:DActors = new DActors();
Call the constructor properly
public var dActors:DActors = new DActors();
The semicolon after your DActors constructor breaks your code.
public function DActors();
if you change the DActors class to this it will work:
package src.data
{
public class DActors
{
public var me:int = 1;
public function DActors()
{
trace(me);
}
}
}

A very simple Singleton?

Does this work well as a Singleton in actionscript? i.e. are there any gotchas I should be aware of, and is it true that only one instance of AVManager would be created in this case:
Note that I do get the expected output (only one time of "instantiated first time" and numbers follow sequence):
instantiated first time! 1
FILE 1: 2
FILE 2: 3
and finally 4
Here are the files....
AV_CONFIG.as:
package {
public class AV_CONFIG {
public static var AVM:AVManager = new AVManager();
}
}
AVManager.as:
package {
import flash.events.EventDispatcher;
public class AVManager extends EventDispatcher {
public var someConstantData:uint = 1;
public function AVManager() {
trace('instantiated first time!', someConstantData);
}
}
}
Then:
File1.as:
package {
import AV_CONFIG;
import flash.display.Sprite;
public class File1 extends Sprite {
public function File1() {
AV_CONFIG.AVM.someConstantData++
trace('FILE 1:', AV_CONFIG.AVM.someConstantData);
}
}
}
File2.as:
package {
import AV_CONFIG;
import flash.display.Sprite;
public class File2 extends Sprite {
public function File2() {
AV_CONFIG.AVM.someConstantData++
trace('FILE 2:', AV_CONFIG.AVM.someConstantData);
}
}
}
Main.as (the DocumentClass):
package {
import AV_CONFIG;
import flash.display.Sprite;
public class Main extends Sprite {
public function Main() {
var f1:File1 = new File1();
var f2:File2 = new File2();
AV_CONFIG.AVM.someConstantData++
trace('and finally', AV_CONFIG.AVM.someConstantData);
}
}
}
Generally with singletons you want to:
Limit or dissolve the ability to create instances of that class.
Create a means of getting an instance of that class statically.
Example:
public class AvManager
{
private static var _instance:AvManager;
internal static var created:Boolean = false;
public function AvManager()
{
if(AvManager.created)
{
throw new Error("Cannot created instances of AvManager, use AvManager.instance.");
}
AvManager.created = true;
}
public static function get instance():AvManager
{
if(_instance == null)
{
_instance = new AvManager();
}
return _instance;
}
public function test():void
{
trace("Working.");
}
}
Where you could now use:
AvManager.instance.test(); // Working.
The biggest gotcha is allowing global access to something if its state can be changed. If this is a project where you expect the codebase to be maintained for longer than a week or so and you think it's likely to have more than 500 lines of code, I'd strongly suggest avoiding doing this--I can tell you from experience that in a large project it can be difficult to impossible to figure out which of the hundreds of Classes that have access to your Singleton made the change to its state that is causing a given bug.
Next, requirements have a way of changing. What if you suddenly need 2 AVManagers? You'll find that you've created so many baked-in references to your static that changing it will blow the entire project to heck. Again, I speak from experience here. If you use dependency injection (which is just a scary way of saying that Classes that need an AVManager have a property that is populated from the outside), then these types of changes become easy...just give them a different AVManager, done.
Finally, if you have any pretensions of wanting to do Test Driven Development, using globals/statics in this way will essentially make all that code untestable. You can't provide an alternate AVManager for testing, since all the Classes with a dependency on it are hard-wired to go get that specific one.
Good luck!
Yeah this works fine, a different method is to put an AVManager right in its own class file at the top:
private static var AVM:AVManager = new AVManager();
and get it when required with a function in the AVManager class like this:
public static function GetInstance():AVManager {
return AVM;
}
This setup isn't necessary but provides some nice little protection by disallowing direct access.
Good luck with your project.
See this code as an attempt for creating something different.
An other Singleton in AS3 :
First an Interface :
package test {
public interface Foo {
function func0():void;
function func1(arg:String):String;
}
}
And then a Singleton :
package test {
public class BASIC_FOO {
public static const BASIC_FOO:Foo = new BasicFoo();
}
}
import test.Foo;
class BasicFoo implements Foo {
public function func0():void {
}
public function func1(arg:String):String {
return arg;
}
}

AS3 override public function both are called?

I am a little confused by this concept.
If I override a public function in a base class, I would have thought that this override function is called and the original is ignored? though this doesn't seem to be the case...
public class AbstractScreen extends Sprite
{
public function AbstractScreen()
{
}
public function updateLanguage():void
{
trace("WARNING: need to override public function updateLanguage()");
}
}
public class Start extends AbstractScreen
{
override public function updateLanguage():void
{
title.text = _model.language.start
title.setTextFormat(titleFormat);
}
}
public class ViewManager extends Sprite
{
private var _model:Model;
private var _screens:Array;
public function ViewManager(model:Model)
{
_model = model;
_model.addEventListener(AppEvent.INIT_VIEW, initViews);
_model.addEventListener(AppEvent.UPDATE_VIEW, updateView);
_model.addEventListener(AppEvent.CHANGED_LANGUAGE, changeLanguage);
}
private function initViews(e:AppEvent):void
{
trace("View Manager: initViews");
_screens = new Array(new Start(_model), new TakePhoto(_model));
dispatchEvent(new ViewEvent(ViewEvent.VIEW_READY));
}
private function changeLanguage(e:AppEvent):void
{
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}
}
}
If my model dispatches a CHANGED_LANGUAGE event, the text in the views gets updated, But I also get a trace of "WARNING: need to override public function updateLanguage()" What could I be doing wrong?
You are right, this should not call the base class function. Are you sure there is no call to
super.initLanguage()
within your override?
Most IDE's add this call in the function body automatically, if they create an override for you.
EDIT
From your edit I see your are iterating over two objects of the types Start and TakePhoto. I assume TakePhoto is also derived from AbstractScreen and the trace may be comming from this one.
Also I suggest to use the abstract base class in your iteration.
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}

AS3 - Abstract Classes

How can I make an abstract class in AS3 nicely?
I've tried this:
public class AnAbstractClass
{
public function toBeImplemented():void
{
throw new NotImplementedError(); // I've created this error
}
}
public class AnConcreteClass extends AnAbstractClass
{
override public function toBeImplemented():void
{
// implementation...
}
}
But.. I don't like this way. And doesn't have compile time errors.
abstract classes are not supported by actionscript 3. see http://joshblog.net/2007/08/19/enforcing-abstract-classes-at-runtime-in-actionscript-3/
the above reference also provides a kind of hackish workaround to create abstract classes in as3.
Edit
also see http://www.kirupa.com/forum/showpost.php?s=a765fcf791afe46c5cf4c26509925cf7&p=1892533&postcount=70
Edit 2 (In response to comment)
Unfortunately, you're stuck with the runtime error. One alternative would be to have a protected constructor.... except as3 doesn't allow that either. See http://www.berniecode.com/blog/2007/11/28/proper-private-constructors-for-actionscript-30/ and http://gorillajawn.com/wordpress/2007/05/21/actionscript-3-%E2%80%93-no-private-constructor/.
You may Also find these useful: http://www.as3dp.com/category/abstract-classes/ and, in particular, http://www.as3dp.com/2009/04/07/design-pattern-principles-for-actionscript-30-the-dependency-inversion-principle/
package
{
import flash.errors.IllegalOperationError;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
public class AbstractClass
{
public function AbstractClass()
{
inspectAbstract();
}
private function inspectAbstract():void
{
var className : String = getQualifiedClassName(this);
if (getDefinitionByName(className) == AbstractClass )
{
throw new ArgumentError(
getQualifiedClassName(this) + "Class can not be instantiated.");
}
}
public function foo():void
{
throw new IllegalOperationError("Must override Concreate Class");
}
}
}
package
{
public class ConcreteClass extends AbstractClass
{
public function ConcreteClass()
{
super();
}
override public function foo() : void
{
trace("Implemented");
}
}
}
In AS3 would just use interfaces to make sure all functions are implemented at compile time.
I know it different but does the trick for an example such as the one above.
As long as they don't permit non-public constructors in actionscript, you'd have to rely on run time errors for abstract classes and singletons.