AS3 Cast Vector to Array - actionscript-3

var leaderboardRowVOs:Vector.<LeaderboardRowVO> = new Vector.<LeaderboardRowVO>();
goes to another part of the system as an Object, and I'm trying to cast it back to actual type
notification.getBody() as Vector.<LeaderboardRowVO> //throwing error

There are two ways of type casting in AS3:
// Casting
// 1: returns null if types are not compatible,
// returns reference otherwise
notification.getBody() as Vector.<LeaderboardRowVO>
// Converting
// 2: throws exception if types are not compatible,
// returns reference otherwise
Vector.<LeaderboardRowVO>(notification.getBody())
Case 1 does not throw error, if you have such a behaviour, there must be an error in notification.getBody() method.
EDIT: #divillysausages made a clever comment about case 2 actually creating an object of another type. This is not the case here. This is what mostly happens for native types with one exception: the Array class. Some of the native classes have top level converting functions. Refer to adobe livedocs for the complete list of them. A Vector can be instantiated this way by passing an Array of appropriate types to the Vector() function.

Something else must happen to the Vector within your class because it's valid to cast a vector to Object and then back to Vector. This simple test shows it:
var v:Vector.<int> = new Vector.<int>();
v.push(1);
v.push(2);
var o:Object = v as Object;
var v2:Vector.<int> = o as Vector.<int>;
trace(v2[0]); // Output "1"
trace(v2[1]); // Output "2"
So your problem must be somewhere else.

Related

ActionScript - variable declaration difference

What is the difference between:
var arr3 = new Vector.<int>(6);
to
var arr3:Vector.<int> = new Vector.<int>(6);
Thanks!
It's the difference between declaring a variable type and not. While declaring a type is optional in AS3, best practice is to always declare a type.
The effect on your code this has is that if you declare a type, it will only compile and run properly if values of that type are assigned to the variable, and it will always be treated strictly as that type of object and nothing else. This is called "type safety". If you don't declare a type, you can assign anything to that variable and write code as if its any kind of object -- which may sound convenient, but it ends up making the code much more confusing, fragile and error prone.
Also note that not declaring a type is equivalent to declaring it as a "wildcard" type, like this: var arr3:*
Here's an example of untyped vs typed variables in code:
var untyped:*;
var string:String;
var number:Number;
var integers:Vector.<int>;
untyped = 1; // ok
untyped = "hello"; // ok
untyped = new Vector.<int>(); // ok
string = 1; // compile error
string = "hello"; // ok
string = new Vector.<int>(); // compile error
number = 1; // ok
number = "hello"; // compile error
number = new Vector.<int>(); // compile error
integers = 1; // compile error
integers = "hello"; // compile error
integers = new Vector.<int>(); // ok
if (untyped == 1) // ok
if (untyped == "hello") // ok
if (untyped.fixed) // compiles ok, but throws runtime error if "fixed" not defined on non-dynamic object
if (string == 1) // compile error, invalid comparison
if (string == "hello") // ok
if (string.fixed) // compile error, "fixed" not a property of String
if (number == 1) // ok
if (number == "hello") // compile error, invalid comparison
if (number.fixed) // compile error, "fixed" not a property of Number
if (integers == 1) // compile error, invalid comparison
if (integers == "hello") // compile error, invalid comparison
if (integers.fixed) // ok
These compile errors serve to show you mistakes you (or other developers) make before they become hard to hunt down problems in your SWF. For example, consider this untyped code:
var value = "hello";
if (value.x < 10) { }
That code doesn't make much sense, but it will compile. Then you will hit a runtime error when it tries to execute the if statement and can't find x on String "hello". In real life you might have a lot of hunting around to do to figure out what's wrong, especially if those 2 lines are not in close proximity to each other. However, if the programmer had specified a type on the variable, it would make the code more type safe:
var value:Point;
if (value.x < 10) { }
In this case the code would not compile if you tried to assign value = "hello". The compiler would also validate that x is a property of type Point. If it wasn't, you'd get a compile error there, too. It even knows that x can be compared using < because it's a Number. This is all helpful to catch errors early rather than later.
In addition to making the code more clear to programmers, it also makes it more clear to authoring tools -- most authoring tools will give you much better code-completion suggestions for typed objects, since it knows exactly what properties and methods that type of object has.
For these reasons and probably others, you'll rarely find AS3 code examples that don't use strict type declarations, and most programmers (including me) will advise you always use them.
Use second option. In first case you will get warning message:
Warning: Error code: 1008: variable 'arr3' has no type declaration.
The first variable is untyped. If you declare a variable, but do not declare its data type, the default data type ***** will apply, which actually means that the variable is untyped. If you also do not initialize an untyped variable with a value, its default value is undefined.
The second one is typed as Vector.. A variable declared with the Vector. data type can only store a Vector instance that is constructed with the same base type int. For example, a Vector that's constructed by calling new Vector.() can't be assigned to a variable that's declared with the Vector. data type.
Good answers from everyone. But the real answer goes a lot further. In case 1 the variable has no type and in case 2 the variable has a type. The difference is that in the second case the compiler is able to provide you with information in case something in your code goes wrong. In the first case the compiler might be able to provide some info or even no info at all in case something goes wrong in your code. If you work with untyped variables (case 1) you the developer are on your own if there's any error in your code. You'll be the one to look for them and try to fix them. In the second case the compiler will tell you where there's an error and most likely why there's an error.

What is the use in having the valueOf() function?

Why is the valueOf() function present in everything in AS3? I can't think of an instance when this isn't redundant. In terms of getting a value, x and x.valueOf() are completely the same to me (except that one probably takes more CPU cycles). Furthermore even though they may not be the same in terms of setting something, x.valueOf() = y (if even legal) is just completely pointless.
I am confident though that this is here for a reason that I'm just not seeing. What is it? I did try Googling for a minute. Thanks!
As you say, its completely redundant.
The valueOf method is simply included so that ActionScript 3 complies with the ECMA language specification (obviously there are other requirements to be an ECMA language - i believe toString is another example).
Returns the primitive value of the specified object. If this object does not have a
primitive value, the object itself is returned.
Source: Adobe AS3 Reference http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Object.html#valueOf()
Edit:
A primitive value can be a Number, int, bool, etc... They are just the value. An object can have properties, methods, etc.
Biggest difference, in my opinion though:
primitive2 = primitive1;
In this example, primitive 2 contains a copy of the data in primitive 1.
obj2 = obj1;
In this one, however, ob2 points to the same object as obj1. Modify either obj1 or obj2 and they both reflect the change, since they are references.
In short, valueOf is used when you want to see the primitive representation of an object (if one exists) rather than the object itself.
Here is a clear example between
Value Vs. ValueOf:
Value = Thu Jan 2 13:46:51 GMT-0800 2014 (value is date formatted)
ValueOf = 1388699211000 (valueOf is in Raw epoch)
valueOf isn't useless. It allows an Object to provide a value for an expression that expects a primitive type. It's available in AS3 as well as JavaScript.
If someone wrote a function that takes an int, you could pass it your object (more precisely, it passes the result of your object's valueOf() function).
The usefulness is tempered by 1) the fact that the Object isn't passed, so it's only an Object in the outermost scope, and 2) the fact that it's a read-only operation, no assignment can be made.
Here're a couple concrete examples off the top of my head:
Example 1: A Counter class that automatically increments its value every time it's read:
class Counter
{
private var _cnt:int = 0;
public function Counter() { }
public function valueOf():int
{
return _cnt++;
}
public function toString():String { return ""+valueOf(); }
}
Usage:
var c:* = new Counter();
trace(c); // 0
trace(c); // 1
trace(2*c+c); // 2*2+3 = 7
trace(c); // 4
Notes:
I added the toString() pass-through, since functions that take String prefer toString over valueOf.
You must type c as * and not Counter, otherwise you'll get a compiler error about implicit coercion of Counter to Number.
Example 2: A (read only) pointer type
Let's say you have an array of ints, and you want to have a reference (aka pointer) to an element in the array. ECMA scripts don't have pointers, but you can emulate one with valueOf():
class ArrayIntPointer
{
private var arr:Array;
private var idx:int;
public function ArrayIntPointer(arr:Array,
idx:int)
{
this.arr = arr;
this.idx = idx;
}
public function valueOf():int
{
return arr[idx];
}
public function toString():String { return ""+valueOf(); }
}
Usage:
var arr:Array = [1, 2, 3, 4, 5];
var int_ptr:* = new ArrayIntPointer(arr, 2);
// int_ptr is a pointer to the third item in the array and
// can be used in place of an int thanks to valueOf()
trace(int_ptr); // 3
var val:int = 2*int_ptr+1;
trace(val); // 7
// but it's still an object with references, so I
// can change the underlying Array, nand now my
// object's primitive (aka, non-Object types) value
// is 50, and it still can be used in place of an int.
arr[2] = 50;
trace(int_ptr); // 50
// you can assign int_ptr, but sadly, this doesn't
// affect the array.
That's pretty slick. It'd be really slick if you could assign the pointer and affect the array, but unfortunately that's not possible, as it assigns the int_ptr variable instead. That's why I call it a read-only pointer.

Actionscript check custom object defined type (not actual type)

Suppose I have a custom object variable that is set as null and I want to check it's type definition. How do I do it?
var a:MyObject = null;
// how do I check if a is MyObject?
//
// a is MyObject == false
// a instanceof MyObject == false
// getQualifiedClassName(a) <-- Exception
// typeof(a) == "object"
// describeType(a) <-- Exception
// a.constructor <-- Exception
// a.prototype <-- Exception
I think you're misunderstanding the way all of those examples in your question work.
They don't check the type that is associated with a variable - they check the type of the instance assigned to that variable. Here is a good example of why your examples don't make sense:
var prop:DisplayObject = new MovieClip();
trace(prop is MovieClip); // true
If this worked the way you thought it does, you would actually get false here.
All you're doing when you create a variable and give it a type is telling the compiler what type of instances it expects to see assigned to that property, and to throw an error if something that is not an instance of the expected type is assigned to it.
I don't think there is a way to determine what type a variable expects. Moreover, I think if you see a need to be checking what type a variable is expecting at runtime, then you're doing something terribly wrong.

Compare two interfaces using "is"

I am not sure if I am missing something here. I would like to compare two classes that uses the same interface. Is this possible? I understand that the is operator compares classes, but is there any similar function when you use interfaces?
// works
var effect1 : CrazyEffect = new CrazyEffect();
var effect2 : SaneEffect = new SaneEffect();
trace(effect1 is effect2) // false
// does not work
var effect1 : ISoundEffect = new CrazyEffect();
var effect2 : ISoundEffect = new SaneEffect();
trace(effect1 is effect2)
1067: Implicit coercion of a value of type ISoundEffect to an unrelated type Class.
Note the differences between concepts of a class and of an object. The former is a data type whereas the latter is a runtime instance of it, a variable. is operator can not compare one variable to another.
According to language reference
is Operator
Evaluates whether an object is compatible with a specific data type,
class, or interface. Use the is operator instead of the instanceof
operator for type comparisons. You can also use the is operator to
check whether an object implements an interface.
In other words, compiler expects the first operand to be a variable whereas the second operand should be a type identifier.
var sample:String = "Object is an instance of a class.";
^^^ ^^^
variable type identifier
However effect2 is not a type identifier but a variable. Hence the error message.
Unfortunately there is no generic operator to test for interface commonality. The only alternative is:
trace((s is ISoundEffect) && (t is ISoundEffect));
Update
Checking whether objects are instances of a same class can be done by comparing class names:
if (getQualifiedClassName(effect1) == getQualifiedClassName(effect2)) {
// true
}
For in depth discussion see Get the class used to create an object instance in AS3
Even though it will work with getQualifiedClassName, there's a better method to check whether two objects are instances of the same class:
a['constructor'] === b['constructor']
getQualifiedClassName is very slow and CPU intensive. Since the above code just compares property values it is lightning fast. And yes, constructor IS a property of every object, however FB will complain if you try to access it using dot-notation, that's why I use dynamic property access.

AS3 httpservice - pass arguments to event handlers by reference

I have this code:
var service:HTTPService = new HTTPService();
if (search.Location && search.Location.length > 0 && chkLocalSearch.selected) {
service.url = 'http://ajax.googleapis.com/ajax/services/search/local';
service.request.q = search.Keyword;
service.request.near = search.Location;
} else
{
service.url = 'http://ajax.googleapis.com/ajax/services/search/web';
service.request.q = search.Keyword + " " + search.Location;
}
service.request.v = '1.0';
service.resultFormat = 'text';
service.addEventListener(ResultEvent.RESULT, onServerResponse);
service.send();
I want to pass the search object to the result method (onServerResponse), but if I do it in a closure it gets passed by value. Is there a way to do it by reference without searching through my array of search objects for the value returned in the result?
I'm not quite sure what you want to do here.
Parameters are indeed passed by value. In the case of objects (and by object here I mean everything that has reference semantics, i.e. everything but Booleans, Number, ints, Strings, etc), a reference to them is passed by value, so in your function you have a reference to the original object, not a reference to a copy of the object.
So, if you want to dereference the object and change some value or call some method on it, you'll be ok. The only thing that wont work is changing the reference itself; i.e. you can't null it out or assign a new object to it:
function dereferenceParam(param:Object):void {
param.someInt = 4;
param.someMethod();
}
function reassignParam(param:Object):void {
param = null;
// or
param = new Object();
}
dereferenceParam() will work as most people expect, reassignParam won't.
Now, the only possible "problem" I think you could have as per your last paragraph would be that you want to remove or null out the search object from some array you have. I'm afraid in that case, the only way would be to loop through the array.
How are you determining that you have received a copy of the object?
To my knowledge, (non-intrinsic) objects are almost never copied by value. The only exception are dispatched Event objects, but that is explicitly documented.