ActionScript 3.0 class extends - actionscript-3

SCENARIO:
I have the class characterObject and n class that extends (cat, dog, bird, n...)
public class characterObject
{
public static var totalCounter:int;
}
public class cat extends characterObject
public class dog extends characterObject
public class bird extends characterObject
Is it possible for the extended classes to listen to changes to static variables (eg totalCounter) in the main class with or without events?

This is possible using a combination of getter/setter functions and events.
Getters and Setters, in actionscript, are functions that can be accessed like variables, giving you the ability to execute functions on variable changes.
public class characterObject
{
private static var _totalCounter:int;
protected static var internalDispatcher:EventDispatcher = new EventDispatcher();
public static function get totalCounter():int
{
return _totalCounter;
}
public static function set totalCounter(value:int):void
{
_totalCounter = value;
var event:Event = new Event("totalCounterChanged");
internalDispatcher.dispatchEvent(event);
}
}
As you can see we have a protected static event dispatcher called internalDispatcher, we can listen to events from this object only if we have extended the characterObject class. By hiding the true totalCounter behind the getter/setter we can dispatch an event whenever something changes it's value.
We can then listen for this event in our extended classes:
public class cat extends characterObject
{
public function cat()
{
super();
internalDispatcher.addEventListener("totalCounterChanged",totalChangedHandler);
}
public function totalChangedHandler(event:Event):void
{
//Your code here;
}
}
Depending on your requirements it maybe better to have your Event Handlers be static also to reduce the same code being executed multiple times without a change in output.

Related

AS3 - how to extend this function

This is first class with "gordz()" function
public class Model extends Object implements IModel
{
public static function gordz() : void
{
newobject = gallas.pop();
}
}
Now i try to override the function but i still want that old code is executed... How can i extend this function correctly?
public class LOL extends Model
{
override public static function gordz() : void
{
... //New code + execute old code
}
}
Neither super
You cannot use the super statement in a static method.
nor override
You cannot use the override attribute on any of the following:
[...]
Static methods
can be used in a static method.
Whatever you are trying to do should be accomplished in a different way.

Actionscript 3.0 - Get variable from superclass to new object

How do I do this?
public class SuperClass extends MovieClip {
public static var test:String = 'Hello world';
}
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit();
addChild(Unit);
}
}
public class Unit extends MovieClip {
public function Unit() {
//Get variable:test from SuperClass??
trace(SubClass.test); //Error
}
}
Hope you understand what I want to do?
Want to get the variable 'test' from the SuperClass in my new Unit added in SubClass.
Thanks!
In this case your class named SubClass uses the Unit class through composition, not inheritance. As such the Unit class knows nothing about SubClass or SuperClass or any of their properties like the test property.
You can, however, pass a value into the Unit class through it's constructor (or just set a value directly onto a property of the Unit class):
(showing the last two classes only)
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit(test);
addChild(Unit);
}
}
public class Unit extends MovieClip {
private var test:String;
public function Unit(test:String) {
this.test = test;
}
}
[Edit]
Since your Unit class needs to access many properties of SubClass (and/or SuperClass), you might want to just pass an instance of SubClass to Unit:
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit(this);
addChild(Unit);
}
}
public class Unit extends MovieClip {
private var subClass:SubClass;
public function Unit(subClass:SubClass) {
this.subClass = subClass;
trace(subClass.text);
}
}
How you actually solve this depends on your use case. But there is no fundamental shortcut to do what you are asking.

How to Access Properties And Methods of a Class Without Extending or Instantiating?

Let's say I have a defined ClassA.
ClassB extends ClassA and there's a Movie Clip instance on the stage linked to ClassB.
How would ClassC access the properties and methods of ClassB without extending ClassB or creating a new instance of ClassB?
The way I'm currently doing it is by referencing the stage instance linked to ClassB and then using the dot syntax to access ClassB instance variables, and this works only if the the accessed variables are public or internal, depending on what package ClassC is part of. I would like to know if there's a better, cleaner way to accomplish this.
Edit: Code example.
package com.core.stage.classes {
import flash.display.MovieClip;
public class ClassA extends MovieClip {
public var classAvar:uint = 0;
public function ClassA() {
}
protected function classAfunction(funPar:uint):void {
classAvar = 2 * funPar;
}
}
}
package com.core.stage.classes {
import com.core.stage.classes.ClassA;
public class ClassB extends ClassA {
public function ClassB() {
classAfunction(10);
}
}
}
package com.core.stage.classes {
import flash.display.MovieClip;
public class ClassC extends MovieClip {
private var classBreference:*;
public function ClassC() {
classBreference = Object(parent);
trace(classBreference.classAvar); // Outputs 20.
}
}
}
So what I basically want to know is if there's a better way to get the value of classAvar (which was declared in ClassA, got a value after calling the method in ClassB) while working in ClassC.
Solved:
Ok, after some research and an idea I got from daniel.sedlacek, it seems that I have found the solution that best suits my needs.
in ClassB:
private static var _instance:ClassB;
public function ClassB() { // constructor
_instance = this;
}
public static function get FUN_GetInstance():ClassB {
return _instance;
}
in ClassC:
private var MC_VariablesContainer:ClassB
MC_VariablesContainer:MC_ClassB = ClassB.FUN_GetInstance
and this works only if the the accessed variables are public or internal, depending on what package ClassC is part of. I would like to know if there's a better, cleaner way to accomplish this.
This is one of the base principles of OOP. You can not get private and protected properties or methods. If you want to get them, you should make them public or internal.
A)
Don't do it, think of better architecture that will respect encapsulation loose coupling.
B)
If you have to do it, you can use static global register and make all stage instances (like your ClassB) assign to it, for instance:
in ClassB:
StaticRegister.assign(this);
in StaticRegister:
publis static var register : Array = [];
public static function assign(instance : Object) : void {
array.push(instance);
}
And then get it out of there in similar fashion. But it's really dirty to do it like this.
C)
If there is only one instance of ClassB you can give it static - singleton like - accessors:
In ClassB:
private static var instance : ClassB;
publis static function getInstance() : ClassB {
return instance;
}
In Constructor:
public class ClassB() {
instance = this;
}
More about complete singletons: www.actionscript.org or Google or Wikipedia.

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();
}

Can Objects not on display-list access root or any object that is added on displaylist?

Suppose in document class
public class Test extends MovieClip
{
public function Test()
{
var object1:ClassA = new ClassA();
//addChild(object1);
object1.accessRoot();
}
}
public class A extends MovieClip
{
public function accessRoot()
{
var mc : MovieClip = root as MovieClip;
mc.box.visible = false;
}
}
Now box is placed at stage. but when Class A is added to Test Class, it works and when object of Class A is not added in Test constructor, root becomes in-accessible. Is there any way that objects not on display-list can access root or display-list objects??
I would not recommend having your classes fiddle around with root or stage, it's way better to dispatch events and have the proper encapsulation.
Hacky way:
public class A extends MovieClip
{
private var _root:MovieClip;
public function A(root:MovieClip)
{
_root = root;
}
public function accessRoot()
{
_root.box.visible = false;
}
}
Proper way:
public class A extends MovieClip
{
public static const ACCESS_ROOT:String = "access_root";
public function accessRoot()
{
dispatchEvent(new Event(ACCESS_ROOT));
}
}
// in your document class
var myA:A = new A();
myA.addEventListener(A.ACCESS_ROOT, handleAccessRoot);
public function handleAccessRoot(e:Event):void{
box.visible = false;
}
I normally create a sort of base class that holds a reference to the document class - or "main" class. Anything that I create from here that should need reference to anything defined in Main would extend Element. Example:
The Main class (or document class):
public class Main extends MovieClip
{
/**
* Constructor
*/
public function Main()
{
var obj:MyElement = new MyElement();
obj.main = this;
// stage will be outputted
}
}
Element - which stores reference to the main class.
It also contains an init() function which I generally use in place of a constructor by overriding it.
public class Element extends MovieClip
{
private var _main:Test;
public function set main(m:Main):void
{
_main = m;
init();
}
/**
* Called when _main is defined
*/
protected function init():void
{
// override me
}
public function get main():Main{ return _main; }
}
And here's how you would use Element as a base class for your classes:
public class ClassA extends Element
{
/**
* Override init rather than using a constructor
*/
override protected function init():void
{
trace(main.stage);
}
}
The only thing really to note is that you of course have to set the _main property whenever you create an object. (as shown on line 9 of Main).