How do I call a private function from an external ActionScript3 document? I'm working in Flash Builder 4, and I need to call a private function from an external AS3 document. I think I've imported it correctly....
import myapp.utils.WebcamFaceDetector;
import myapp.utils.FaceDetector;
But I want to call a function from "FaceDetector". Here's the part of the code in FaceDetector...
public class FaceDetector
{
private var detector :ObjectDetector;
private var options :ObjectDetectorOptions;
private var faceImage :Loader;
private var bmpTarget :Bitmap;
private var view :Sprite;
private var faceRectContainer :Sprite;
private var tf :TextField;
private function FaceDetector() {
initDetector();
}
//...
}
I want to call "private function FaceDetector()" to initiate at a certain point in another AS3 file. How do I properly declare it and get it to run?
The only way to access a private function it is to declare it as public or introduce an extra function and declare that as public.
The private attribute is meant to restrict access to that Class alone.
What you can do is create a protected function that subclasses your FaceDetector class and that gives you access but maybe not in the way that you want to use it.
On closer inspection you are using a private constructor (unless this is not your package) which prevents instantiation from other classes so I am not sure what you are really trying to accomplish.
If is was a normal private function (not a constructor) you could also register it to listen for events and and dispatch the event from where-ever you need it from.
The only proper way I know of to use private constructors other than utility classes are Singletons and that cannot even be done in ActionScript 3 (private constructors)
From your example code, the FaceDetector function is the contructor of the FaceDetector class. This means it is called when you construct a new instance of FaceDetector e.g.
var faceDetectorInstance:FaceDetector = new FaceDetector();
your constructor should be public not private. AS3 does not support private constructors.
you should make your initDetector method public, so you can call that directly e.g.
public function initDetector():void
{
//Do Stuff Here...
}
First, you cannot call a private class. The private keyword purpose is to stop external classes, including subclasses from calling the function.
Second, FaceDetector has the same name as the class. This means it is the constructor and is automatically called when you create a new instance of the class.
PS. Constructors in ActionScript 3.0 must be public
Related
I'm developing a game in AS3. There is a Weapon superclass, which contains methods such as shoot and reload, which will behave the same across all weapons.
The specific weapons, such as Pistol, Shotgun inherit from this class so they can use these methods. They have public static variables, such as what type of bullet to shoot, rate of fire, bullet spread, that make them unique, and are used in these methods. They need to be public static variables so I can look them up from somewhere else in the core when all I've got there is the type of weapon that was fired.
Is this how I should be trying to do it? How does the Weapon superclass access these variables?
public static const RATE:uint = 2;
That is accessed by the Weapon class either as Weapon.RATE or as RATE. Scope works a little weird when it comes to static objects. I personally don't think you should be able to access the static objects with just RATE, but it works.
Subclasses do not inherit static properties and methods. They belong solely to the class they are created in (which makes sense if you know what a static object really is). So for all classes, even classes that extend Weapon, you must access a public static object via Weapon.RATE.
There is an oddity I have noticed however. If you use the protected access modifier instead of public, classes can access static objects in their super classes via RATE, as if it were created within the class itself. I don't know the logic behind that, but it works.
So:
public class Weapon {
protected var RATE:uint = 2;
public var RATE2:uint = 5;
}
public class Gun extends Weapon {
trace( RATE ); // output 2
trace( Weapon.RATE ); // output 2
trace( RATE2 ); // output Error, access of undefined property
trace( Weapon.RATE2 ); // output 5
}
EDIT: In response to the first comment:
The way superclasses work, an object that extends a class has access to all public and protected objects in the super class.
So let's say the weapon class is this:
public class Weapon {
public function shoot():void{}
protected function reload():void{}
private function aim():void{}
}
You would access those methods within the subclass like you would in the super class itself:
public class Pistol extends Weapon{
public function Pistol() {
this.shoot(); // works
this.reload(); // works
this.aim(); // doesn't work because it is private
}
}
Now if you are looking to abstract things further, you can set up properties within your super class with a protected or public modifier with a default value for all weapons. In your superclass methods, you simply call these values. In the subclass, you change them to be whatever you need them to be
public class Weapon {
public var rate:uint = 2;
public function shoot():void{
// use this.rate here
}
protected function reload():void{}
private function aim():void{}
}
public class Pistol extends Weapon{
public function Pistol() {
this.rate = 5; // value of rate is now 5 and will be used in shoot()
this.shoot(); // works
this.reload(); // works
this.aim(); // doesn't work because it is private
}
}
I am trying to bind to a static function, I designate a binding event name and then fire the event from another static function.
[Bindable(event="dataUpdated")]
public static function string(path:String) :String
{
...
}
private static function updateData() :void
{
//doSomthing;
staticEventDispatcher.dispatchEvent(new Event('dataUpdated'));
}
private static var staticEventDispatcher:EventDispatcher = new EventDispatcher();
My view is not updating when the event is fired, is there a better way to do this?
I have also tried dispatching the event from an instance of the class, I added this staticEventDispatcher as a last resort, but it didn't work.
The point in this if for language translations within the app, MyClass.string('stringPath') will return the translated component text. I need the app text to be updated when the user changes their language.
Binding doesn't work with static properties and methods (see this question for details Binding to static property).
In your case it's better to use the singleton pattern for resource manager and remove static from string and updateData:
MyClass.instance.string('stringPath')
and MyClass:
public static const instance:MyClass = new MyClass();
I would like to extends the Event class to add some events I am using in game.
But I don't want the new Event Class to have the old public static types..
For instance I don't want to have:
NewEventClass.ENTER_FRAME
How do you go about extending the Event class without getting the old types mixed in?
Is there any way to outsmart AS3 to leave out the uneeded types?
Or should I avoid creating a new Event type altogether and just add the new strings?
Extending Event is only really necessary if you want to add some extra properties to it, for example:
public class EnemyEvent extends Event
{
// Constants used to represent event type
public static const ENEMY_KILLED:String = "killed";
// Event properties
public var score:int = 0;
/**
* Constructor
* Retain Event behaviours
*/
public function EnemyEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
So that when you dispatch this event from an enemy you can go:
var evt:EnemyEvent = new EnemyEvent(EnemyEvent.ENEMY_KILLED);
evt.score = myScoreValue;
dispatchEvent(evt);
And then make use of the score property from the listening method within the game engine:
enemy.addEventListener(EnemyEvent.ENEMY_KILLED, _countKill);
function _countKill(e:EnemyEvent):void
{
gameTotalScore += e.score;
if(gameTotalScore > 100) getAchievement();
e.target.removeEventListener(e.type, _countKill); // <-- woudn't work without extending event either
}
If you just need to store constants to use in addEventListener(x, ..), new Event(x), etc then you can just make a class that holds these and doesn't have anything to do with Event:
public class CustomEvents
{
public static const MY_CUSTOM_EVENT:String = "myCustomEvent";
}
So that you can just use these as needed:
new Event(CustomEvents.MY_CUSTOM_EVENT);
addEventListener(CustomEvents.MY_CUSTOM_EVENT, _listener);
The former method is still preferable as it's tidier and more logical.
Additionally; your note about your custom event having constants such as ENTER_FRAME isn't the case anyway, because they are static and belong to Event. You'll get this error if you try access ENTER_FRAME through the example in your answer:
1119: Access of possibly undefined property ENTER_FRAME through a
reference with static type Class.
I have 2 files: Main.mxml with application and one MyObject.as.
I create the instance of MyObject in mxml and can call its every public function from mxml. But what if for some reason I need to call some function declared in mxml from MyObject class? How to do that? I thought that I could pass the reference to main.mxml class into this object but I couldn't figure out what exact class is it (it inherits Application, right, but what exact class is it?)
Thanks
It is of type Main (it takes on the name of the mxml file). You can add a static variable and getter method to it:
private static var _instance : Main;
public static function get instance () : Main {
return _instance;
}
Then let instance refer to this after the application is complete:
private function applicationCompleteHandler():void
{
_instance = this;
}
Don't forget to set applicationComplete="applicationCompleteHandler" in your <mx:Application> tag.
After that you can call Main.instance from anywhere in your program to access the methods and variables.
If you are instantiating the MyObject class in your Main.mxml, you could also accomplish access to a method in Main by passing the method as a Function into the object.
Suppose you have in Main.mxml the function:
private function doSomething():*{
...
}
With an appropriate setter in MyObject.as:
private var _mainFunction:Function;
public function set mainFunction(f:Function):void
{
_mainFunction = f;
}
Then you can pass the method when you instantiate the MyObject class in the mxml:
<*:MyObject mainFunction='doSomething'/>
And now you just call _mainFunction in the MyObject.as code whenever you need it.
Of course, Weltraumpirat's suggestion would be more efficient if you needed to access more than one method and/or variable on your Application.
i've never tried to do this before, so my head a swimming a bit. i'd like to have a public boolean called enabled in myClass custom class. if it's called to be changed, how do i trigger a function from the change?
should i add an Event.CHANGE event listener to my variable? can i do that? or is there a more standard way?
We usually use properties for that.
Properties are just like public variables for the outside -- you can set instance.enabled = true; and so forth.. But you define properties as getters and/or setters functions for the class.
They are the perfect place for custom logic to be executed on value changes.
For example:
public class CustomClass {
private var _enabled:Boolean = false;
public function set enabled(value:Boolean):void {
trace('CustomClass.enabled is now', value);
this._enabled = value;
}
public function get enabled():Boolean {
trace('CustomClass.enabled was retrieved');
return this._enabled;
}
}
Note that they can't have the same name as your private variable and you don't need both of them defined. Actually, you don't even need a variable for a setter/getter. You could use them just like any function -- they just supply you with a different syntax.
For example:
var object:CustomClass = new CustomClass();
object.enabled = false;
if (object.enabled) {
...
}
They are great to expose a simple API, keeping you from rewriting outside code if the class' internals have to change.
AS3 Reference on getters and setters.