ActionScript - variable declaration difference - actionscript-3

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.

Related

AS3: Not getting typeError when calling a function

I'm writing my own language from ActionScript as a personal project (yeah, I guess AS3 is not the best language to build a language from, but never mind that).
NOTE: I have checked several times, and my compiler's option 'Enable Strict Mode' is set to True. I have tried setting it to False to try, but I didnt get a different result.
At any rate, I have a this:
package NodyCode.Classes
{
public class NCString
{
var value:String;
public function NCString(expression:String = "") {
value = expression;
}
public function rindex(substr:NCString, startIndex:int = 0x7fffffff):uint {
//code here
}
}
}
Since I'm writing my own language, I need to make sure functions and methods can take un unlimited number of arguments. For this reason, I'm using an anonymous function so that I can use the apply method. Like so:
//This code is in a class named ClassMethods
public static var StringMethods:Object = {
rindex: function(substr:NCString, startIndex:int = 0x7fffffff):uint {
return this.rindex(substr, startIndex);
}
}
And, somewhere else in my code, I do the call:
return ClassMethods.StringMethods["rindex"].apply(ncstr1, [ncstr2, [5]]);
I would like an error to be thrown whenever the user uses the wrong type of argument.
So, in this case, I call the rindex method on ncstr1, with arguments: substr = ncstr2 and startIndex = [5]. Notice that, according to my anonymous function's definition, startIndex is supposed to be an int, not an Array.
So, I expected an error to be thrown. Instead, though, rindex is called with startIndex = 5.
Why is [5] converted to 5, and is there any way for me to prevent that? If there isn't, I can always work around this problem, but I'd rather not if I can do otherwise.
EDIT: Finally understood that I did not mention I was using an anonymous function.
Are you compiling with strict mode set to false? (See here also.)
The strict option: "Prints undefined property and function calls; also performs compile-time type checking on assignments and options supplied to method calls".
It defaults to true, but if it got set to false somehow, compile-time checks might be disabled. I'd check your compiler settings (whether in an IDE or if you're compiling on the command-line) and make sure they're correct.
Okay, so here's what was said in the comments:
I did have my compiler on strict mode. The reason for which I was not getting an error is because I was using the apply method of an anonymous function. The type checks are loosened when using the apply method. That's why [5] was coerced to 5.
There is apparently no way to prevent this.

AS3: Is it possible to give a vector function argument a default value?

I have a function where I'd like to make a vector argument optional-- that is, something like this:
public function test(arg1:int, arg2:Vector.<int> = new Vector.<int>(5)) {}
So in that example, I want the first argument to be required, and an optional vector passed in. If the second argument is not provided, create an int vector with 5 elements instead. It throws a compile error: "Parameter initializer unknown or is not a compile-time constant."
Making the argument not optional works, as in:
public function test(arg1:int, arg2:Vector.<int>) {}
But that's not exactly what I'm looking for. Doing some searching I found a supposed workaround, which is
public function test(arg1:int, arg2:Vector.<int> = null) {}
But that doesn't compile either.
I've already moved on in my code with a workaround just to be done with it, but I'm still curious. Can you have a vector as a default argument, and how?
I don't think this is possible. Probably just because the compiler was never programmed to handle this situation because optional parameters do work with many other datatypes in AS3. I did some research and other have reported the same issue as you with no success in setting an empty vector object in the function declaration.
I would simply do the following if you haven't already:
var myDefaultVector:Vector.<int> = new Vector.<int>(5);
function test(arg1:int, arg2:Vector.<int> = null) {
if( arg2 == null ) {
arg2 = myDefaultVector;
}
// rest of your code
}
I have tried compiling the above code in Flash and it compiled successfully.

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.

AS3 Cast Vector to Array

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.

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.