Using object accessors in AS3 - actionscript-3

I was looking at a javascript code here:
https://www.w3schools.com/js/js_object_accessors.asp
Where they have shown using object accessors in javascript.
Being a superset of JS, I tried to use it in AS3 but I am getting compiler error
var p = {
get a() {
return 1;
}
};
trace(p.a);
I hope there must be some way to use it in AS3? Any ideas?
I already know about the longer syntax though which of course works:
var p = {
a:function() {
return 1;
}
};
trace(p.a());

AS3 syntax is very different from JavaScript. Variables have type (even if it's just Object). The AS3 reference shows an example of creating a dynamic object, which is really more of an associative array:
var obj:Object = {a:"foo", b:"bar"};
While AS3 does allow for some of the idiosyncracies of JavaScript, I strongly suggest that you treat it like a proper strongly-types programming language (more like C# or Java, than JavaScript) because this leads to cleaner code and better performance (in some cases).
If you know the properties of the object at design time, you should create classes with get/set properties and methods, because these will have much better performance than a dynamic object.
Adding dynamic functions to objects relies on using the Function type.

Yes there are getters and setters in AS3, but they are available in classes only.
Implementation:
package
{
public class ExampleGS
{
public function get a():int
{
return 1;
}
}
}
Usage:
var p:* = new ExampleGS;
trace(p.a); // 1
More info about getters and setters.

Related

Can you navigate the contents of a Vector's index via a String?

Is it possible to do something similar to this in Haxe?
private var _bindingsFiltered:Vector<String>;
_bindingsFiltered = new Vector<String>();
_controller_touched_binding.action = "meta_start";
What I would like to be able to do:
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
I want to be able to override a specific index too (still accessed via a string), with a new value, rather than keep pushing new content to the end of the vector. I have been using 'openfl.utils.Object' to cheat for now but I am looking for a more reliable approach for the long run.
Is there a way to do this in Haxe?
If not, what are my options?
I would also be interested in a solution for this in AS3, if there is one (avoiding the Array class).
My goal is to find a method that I can use in both languages seamlessly (next-to-none, differences).
Vector's cannot be indexed by string in Haxe. A vector is an array with a fixed size. This is the Haxe manual on that subject.
Instead of vectors, you can use a Map.
class Test {
private var vector:Map<String, String> = new Map<String, String>();
public function new() {
var str = 'haxe';
vector[str] = "is great";
trace(vector[str]);
}
static function main() {
new Test();
}
}
https://try.haxe.org/#F74Ba
I think you could do this using flash.utils.Dictionary:
ActionScript
import flash.utils.Dictionary;
...
var _bindingsFiltered:Dictionary = new Dictionary ();
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
Haxe
import openfl.utils.Dictionary;
...
var _bindingsFiltered = new Dictionary<String, String> ();
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
First, do you really want an array / vector / list, or do you really want a hashmap of key / value pairs? How are you using the collection? Why do you want String keys? And related, is this mostly about access symantics (you want to type it this way), or are the runtime reasons you'd want to use strings (serialization / etc)?
From what you've described, it sounds like what you really want is an Object like the ones in AS3/JS/ECMAScript, with square-bracket access symantics -- obj[key]
Yes, you can do that in Haxe. The openfl.utils.Object class is a helper to do exactly this, using Dynamic objects and reflection. It should compile to exactly what you want on all Haxe targets.
In any case, if you'd like to feel like you're not bound to OpenFL, no problem. Copy the openfl/utils/Object.hx file and place it anywhere you like in your project's class path (and update the package statement).
There's nothing particularly OpenFL-ish about that code. It's pure Haxe code with no dependencies. It provides array access with String keys, as well as toString, toLocaleString, propertyIsEnumerable, iterator, isPrototypeOf, and hasOwnProperty functions (which ECMA-folk are used to.)
The transition from AS3/JS to Haxe is a little weird, especially when it comes to dynamic objects, and I've been meaning to blog more about it. ;) Good luck!
ETA: In truth, you probably want to get away from Dynamic/Reflection, and embrace a more type-strict approach. AS3/JS devs don't understand this at first, but it is where the benefits of Haxe come from. If you don't then your Haxe experience is likely to be unplesant.
Short answer: yes, you can.
abstract MyVector<T>(Vector<T>) {
public function new(l:Int) this = new Vector<T>(l);
#:op([]) public function set<K:T>(s:String, v:K) {
switch (s) {
case "FIRST": this[0] = v;
case "SECOND": this[1] = v;
default: return;
}
}
#:op([]) public function get(s:String) {
switch (s) {
case "FIRST": return this[0];
case "SECOND": return this[1];
default: return cast 0;
}
}
}
var mv = new MyVector<String>(2);
mv["SECOND"] = "Second";
trace(mv["SECOND"]); // outputs Second
You can inline get and set methods if you want.

AS3 How to declare an object without the dreaded "Conflict Exists" error?

I am designing a simple game in Flash and have come across this error. I have no idea how to go about this in actionscript and would appreciate any help.
Basically, I have a switch statement which creates an object of different type depending on each case (as I would prefer not to duplicate the same ten lines of code for each case) and I am getting a "conflict exists with definition in namespace internal" compiler error and I think I understand why.
switch(power){
case 1:
var Pow:objectOne = new objectOne();
break;
case 2:
var Pow:objectTwo = new objectTwo();
break;
}
My question however is this - what is the proper way of going about this?
I initially thought of declaring the variable before the switch statement which results in an "implicit coercion of a value of type object(One/Two) to an unrelated type Class" error. What am I missing here?
Aside from the compiler error you are experiencing, another problem here is that you are planning on using the pow variable later in your code, yet they are of different types. My suggestion is to use the benefits of Inheritance in OOP and create a base class that your two custom classes can inherit from. That way they are both technically of the same base type, while still giving you the freedom to customize each custom class, while keeping similar functionality in the base class.
Remember, OOP is here to always help you and is there to avoid issues like the one you have come across, but here is how I would do it, and I tested the following implementation in Flash CC 2014 and it compiled successfully:
Example .FLA:
var pow:BaseClass;
var power = 1;
switch(power){
case 1:
pow = new ObjectOne();
break;
case 2:
pow = new ObjectTwo();
break;
}
pow.whichObjectAmI(); // this will simply trace what object pow is
Base Class
package {
public class BaseClass {
public function BaseClass() {
// constructor code
}
public function whichObjectAmI() {
trace("I am the base class");
}
}
}
Object One
package {
public class ObjectOne extends BaseClass {
public function ObjectOne() {
// constructor code
}
override public function whichObjectAmI() {
trace("I am Object One!");
}
}
}
Object Two
package {
public class ObjectTwo extends BaseClass {
public function ObjectTwo() {
// constructor code
}
override public function whichObjectAmI() {
trace("I am Object Two!");
}
}
}
You can always inherit from any of ActionScript's classes as well like MovieClip, Button, etc. And by doing so, you're adding custom functionality on top of their functionality so 1) you don't have to rebuild a bunch of functionality, and 2) giving you the chance to reuse their functionality while adding your own custom code!
Disclaimer: My AS3 is a little rusty ;)
Of what type would the variable Pow be after the switch statement? objectOne or objectTwo? From the compiler's perspective objectOne and objectTwo could be totally different from each other (read: methods, fields,...)
So:
A) Keep variable name for both assignments but declare it before the switch-statement AND use a common base-type (object, MovieClip,...)
B) Have 2 different variables: var PowOne: objectOne and var PowTwo: objectTwo
I think option A would be preferable...

When using the 'Class' datatype, how can I specify the type so I only accept subclass of a specific class?

I've got a method that accepts a parameter of type Class, and I want to only accept classes that extend SuperClass. Right now, all I can figure out to do is this, which does a run-time check on an instance:
public function careless(SomeClass:Class):void {
var instance:SomeClass = new SomeClass();
if (instance as SuperClass) {
// great, i guess
} else {
// damn, wish i'd have known this at compile time
}
}
Is there any way to do something like this, so I can be assured that a Class instance extends some super class?
public function careful(SomeClass:[Class extends SuperClass]):void {
var instance:SuperClass = new SomeClass();
// all is good
}
If you are going to instantiate it anyway, why not accept an object instead which allows you to type it to :SuperClass?
careless(SomeClass);
//vs.
careless(new SomeClass);
Not too much of a problem there as far as your code goes.
There are a few differences though:
The object has to be created, because an object is required. If your function does not instantiate the class under some circumstances, this can be a problem. Additional logic to pass either an object or null can bloat the function call.
If you cannot call the constructor outside that function, it won't
work either.
All that is solved by the factory pattern. Pass a factory as the parameter that produces SuperClass objects.
function careful(factory:SuperClassFactory)
Your requirements:
I want to only accept classes that extend SuperClass
and
I need to pass in a Class so that it can be instantiated many times
by other objects later
Can be met by passing in an instance of the class you need, and using the Object.constructor() method.
public function careful(someInstance:SuperClass):void {
//you probably want to store classRef in a member variable
var classRef: Class = someInstance.constructor();
//the following is guaranteed to cast correctly,
//since someInstance will always be a descendant of SuperClass
var myInst:SuperClass = new classRef() as SuperClass;
}
More reading here.
You can't do that in ActionScript 3. In languages like C# you can do something like (forgive me if the syntax is off):
public void Careless<T>() where T : SuperClass
But AS3 does not have 'generics'. Unfortunately the only way I know how to do what you want is the way you have already done.
A pattern that might be more suitable for your use case might be something like:
class SuperClass
{
public static function careless():void
{
var instance:SuperClass = new SuperClass();
// ...
}
}
The only way to have static type checking in ActionScript 3 is to provide an instance of a class.
It is possible but it's expensive. You can use on a Class (not instance) the:
flash.utils.describeType
You then get an XML with a bunch of information including inheritance for that class. Like I said it's an expensive process and probably creating an instance and checking it will be in most cases faster.

Generic way to get reference to a method's caller?

I have 2 classes representing 2 objects. From the "whoCalledMe" function, I want to find out what object called the function (without passing that information in as an argument). I've used a make-believe property, "caller", that would give me the reference I'm looking for. Is there a generic way I can get a reference to the caller from there?
package {
public class ObjectCallingTheFunction {
public var IDENTITY:String = "I'm the calling function!";
public function ObjectCallingTheFunction() {
var objectWithFunction:ObjectWithFunction = new ObjectWithFunction();
objectWithFunction.whoCalledMe();
}
}
}
package {
public class ObjectWithFunction {
public function whoCalledMe ():void {
trace(caller.IDENTITY); // Outputs: "I'm the calling function!"
}
}
}
It would help to know why you need this, because I have a feeling that you don't really. If the method is anonymous, you can bind the 'this' keyword by using .apply on the method:
var foo:Function = function(arg:int):void
{
trace(this);
};
var bar:Object = {
toString: function():String { return "bar"; }
};
var baz:Object = {
toString: function():String { return "baz"; }
};
foo.apply(bar); // <-- Prints "bar"
foo.apply(baz); // <-- Prints "baz"
If the method is an instance method method however, it's a bound method and thus "this" will always point to the instance of the class it's declared in, no matter if you redefine it by using the apply method. If it's a static method, "this" doesn't make sense and the compiler will catch it.
Other than that, there's really no way short of declaring it as a parameter. There used to be a caller property on the arguments object, but it was deprecated when AS3 was released. You can get a reference to the function itself through arguments.callee, but that's not really what you asked for.
In AS3 you can throw an error and then parse the Stack Trace to find out detailed informations.
You can check here for an example:
http://www.actionscript-flash-guru.com/blog/18-parse-file-package-function-name-from-stack-trace-in-actionscript-as3
If you want to find the called function's name you can follow this example:
http://www.flashontherocks.com/2010/03/12/getting-function-name-in-actionscript-3/
I guess you want to know the caller in debug purpose. if so I would recommend setting a breakpoint in the method/function instead of tracing. When the code breaks you can backtrace the caller and a lot more. Works in Flash IDE as well as Flashbuilder. Google "as3 breakpoints" if you are new to breakpoints.
Here is the official Adobe article on using arguments.callee
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/arguments.html
It includes sample code.
Hope this helps.

Actionscript 3.0 Best Option for Subclassing Vector Class (Flash Player 10)

I would like to take advantage of all the goodness of the newer Vector class for FP10, but it seems it is marked as final.
I am doing some intensive mathematical processing in Actionscript, and repeatedly process arrays of Numbers. I have previously been using my own subclass of Array(I call it NumericArray), with added functions such as sum(), mean(), add(), multiply(), etc. This works very well and allows for some clean OO code. However, I am finding through profiling that about 95% of my processing time occurs in the functions of these objects. I need more performance out of these arrays.
I want to use a Vector, as it provides some performance enhancements. I want to specifically use a Vector.<Number>. Unfortunately, I cannot subclass Vector as it is marked final.
What is the best and cleanest way to imitate what I was previously doing with a subclass of Array, to a Vector.<Number>?
I have thought about passing around Vector.<Number> variables instead of my custom class and just using utility functions to manipulate, but this is not good OO design and will be a pain to use, not to mention ugly.
If adding your additional functionality doesn't require access to protected properties/methods of Vector, you could create a wrapper class for the Vector. Something along these lines?
import flash.utils.Proxy;
import flash.utils.flash_proxy;
use namespace flash_proxy;
public class NumericVector extends Proxy
{
private var vector:Vector.<Number>;
public function NumericVector(vector:Vector.<Number> = null)
{
if(vector == null)
{
this.vector = new Vector.<Number>();
}
else
{
this.vector = vector;
}
}
override flash_proxy function nextName(index:int):String
{
return vector[index - 1].toString();
}
override flash_proxy function nextNameIndex(index:int):int
{
// implementation
}
public function sum():Number
{
// do whatever you intend to do
}
...
}
A way to sidestep this issue might be to use the as3ds (short for actionscript 3 data structures). Whether they can be faster than using Vector, I'm not sure.
How come on this page
http://help.adobe.com/en_US/AS3LCR/Flash_10.0/Vector.html
it says:
"Note: To override this method in a subclass of Vector, use ...args for the parameters, as this example shows:"
??
doesn't that imply that you can subclass a Vector?
James