AS3: cast or "as"? - actionscript-3

Is there any difference of use, efficiency or background technique between
var mc:MovieClip = MovieClip(getChildByName("mc"));
and
var mc:MovieClip = getChildByName("mc") as MovieClip;
?
The choice is just matter of convention, preference or are there cases where you can't use one?

This article describes the differences well:
A key difference between casting and the as operator is the behavior
on failure. When a cast fails in ActionScript 2, null is returned.
When a cast fails in ActionScript 3, a TypeError is thrown. With the
as operator in ActionScript 3, whenever a cast fails the default value
for the datatype is returned.
as also allows you to cast to Array, which wasn't possible before since the conversion function Array() took precedence.
EDIT: concerning performance, using as is reported to be faster than the function call style casting in various articles: [1] [2] [3]. The first article cited looks at the performance differences in depth and reports that as is 4x-4.5x faster.
EDIT 2: Not only is as 4x-4.5x faster in the normal best case, but when you wrap the (cast) style conversion in a try-catch block, and an error actually ends up being thrown, it's more like 30x - 230x faster. In AS3, if you think you're going to do something exceptional (in that it could throw an error) then it's clear that you should always look before you leap. Never use try/catch unless forced to by the API, and indeed that means to never (cast) It also is instructive to look at the performance implications of try/catch even when no exception is thrown. There's a performance penalty to setting up a try/catch block even in the happy case that nothing goes wrong.

Since nobody answered the performance aspect directly yet, and it was in your question, as is dramatically more efficient and faster at runtime than (cast) in AS3.
http://jacksondunstan.com/articles/830
Combined with all the other factors I see absolutely no reason to ever use (cast) and feel it should be avoided completely.
Retracted comment below actually reminds me of a good point as well in regards to this. If you (cast) then you're almost assuredly going to find yourself in a situation where you'll have to try/catch
try{
SubType(foo).bar();
}catch(e:TypeError){
// Can't cast to SubType
}
Which is murderously slow. The only way around that is an is check first
if(foo is SubType){
SubType(foo).bar();
}
Which just seems wrong and wasteful.

AS3 Casting one type to another contains the answer that answers this as well: the "as" keyword assigns null when the conversion fails, otherwise it throws a TypeError.

It is best practice to use the as keyword.
as has the advantage of not throwing an RTE (run-time error). For example, say you have a class Dog that cannot be cast into a MovieClip; this code will throw an RTE:
var dog:Dog = new Dog();
var mc:MovieClip = MovieClip(Dog);
TypeError: Error #1034: Type Coercion failed: cannot convert Dog to MovieClip.
In order for you to make this code "safe" you would have to encompass the cast in a try/catch block.
On the other hand, as would be safer because it simply returns null if the conversion fails and then you can check for the errors yourself without using a try/catch block:
var dog:Dog = new Dog();
var mc:MovieClip = Dog as MovieClip;
if (mc)
//conversion succeeded
else
//conversion failed

Prefer the use of a cast to the use of the as operator. Use the as operator only if the coercion might fail and you want the expression to evaluate to null instead of throwing an exception.
Do this:
IUIComponent(child).document
Not this:
(child as IUIComponent).document
Coding Conventions

(cast) and "as" are two completely different things. While 'as' simply tells the compiler to interpret an object as if it were of the given type (which only works on same or subclasses or numeric/string conversions) , the (cast) tries to use a static conversion function of the target class. Which may fail (throwing an error) or return a new instance of the target class (no longer the same object). This explains not only the speed differences but also the behavior on the Error event, as described by Alejandro P.S.
The implications are clear:
'as' is to be used if the class of an object is known to the coder but not to the compiler (because obfuscated by an interface that only names a superclass or '*'). An 'is' check before or a null check after (faster) is recommended if the assumed type (or a type compatible to auto-coercion) cannot be 100% assured.
(cast) is to be used if there has to be an actual conversion of an object into another class (if possible at all).

var mc:MovieClip = MovieClip(getChildByName("mc"));
will DIRECTLY SET IT AS movieclip
var mc:MovieClip = getChildByName("mc") as MovieClip;
will make mc act like a movieclip, if required type are same

Further to launch or not RTE, or return null, there is a significant difference when we manage errors in a swf loaded into a separate application domain.
Using Loader.uncaughtErrorEvents to handle errors of the loaded swf; if we cast like 'event.error as Error', the resulting error will have the original stack trace (the same that had been caught in the swf that caused the error) while if cast that with Error (event.error), the stack trace of the error will be changed by the current stack trace (in which the cast was made).
Sample Code:
if (event && event.error && event.error is Error) {
debug ("Casting with 'as Error'")
debugStackTrace (event.error as Error);
debug ("casting with 'Error (...)'");
debugStackTrace (Error (event.error));
}
Sample output:
Casting with 'as Error'
ReferenceError: Error # 1056
at Player / onEnterFrame ()
casting with 'Error (...)'
Error: ReferenceError: Error # 1056
at package :: HandlerClass / uncaughtErrorHandler ()
at EventInfo / listenerProxy ()

Related

When to use either type casting or the "as" operator in AS3?

I have seen quite a bunch of codes casting objects from one type to another type, using what I call the "standard" casting, like this:
var myDO:DisplayObject = loader.content;
var myCastedMC:MovieClip = MovieClip(myDO);
However the as operator seems to work the same way, because when I traced both objects I get the same value:
var myAsMC:MovieClip = myDO as MovieClip;
trace(myAsMC,myCastedMC); //both outputs read [object MainTimeline]
So, what is the difference between these two? When do yo use the as operator and when do you use the "standard" casting?
You cast only when you are certain the cast will succeed. If casting fails a runtime error is thrown.
You use 'as' to produce a soft cast that will never throw an error. In that case either the cast succeed or the default value of the datatype is returned (for most object that is null).
Both casts are meant to be used in very different situations but since they are misunderstood often you will see 'as' being used when the coder really meant a direct cast.
If following a cast the coder will not check or need to check if the cast has succeeded then it should have used a direct cast. If following a cast the coder needs to check if the cast has succeeded, he should use 'as'.
It should be explained why hitman answer is not correct. The provided code assume success:
(getChildAt(i) as TextField).text=i.toString();
Meaning coder knows the display list only contains TextField object (or else an error will occur). In that case a direct cast is recommended:
TextField(getChildAt(i)).text = i.toString();
If the display list contains other object types then 'as' can be used:
var field:TextField = getChildAt(i) as TextField;
if(field)//if null then getChildAt(i) is not a TextField
{
//field exist so cast succeeded
}
Good question!
on of their differences is that casting is conversion at compile and "as" is converting at runtime.and one of others is that you can only convert subclasses to superclasses.but "as" converts anything.
let's have an example:
let's say we have a lot of textfields on stage and we don't have them in variables or an array.and we want to change their text by a loop:
for(var i:uint=0;i<numChildren;i++){
var t:TextField=getChildAt(i)
t.text=i.toString();
}
probably you see an error because getChildAtreturns displayObject and displayObject doesn't have text property!
so you must use as here:
for(var i:uint=0;i<numChildren;i++){
(getChildAt(i) as TextField).text=i.toString();
}
H☻pes this helps!

Turning an exception into an IObservable exception

I have the following code:
var s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.Select(ParseToMD);
The ParseToMD is pretty simple:
private static IDocumentMetadata ParseToMD(string marc21XML)
{
return MARC21Parser.ParseForMetadata(marc21XML);
}
Unfortunately, it is quite legal for the ParseForMetadata to throw an exception. I'd very much like to be able to use the normal Rx techniques to deal with the exception. For example:
var goodOrEmpty = s.Catch(Observable.Empty<Tuple<PaperStub, PaperFullInfo>>());
How can I properly protect that Select call so exceptions are correctly turned into IObservable On Error? I'm also going to need to do it for the others (StartAsync).
A pattern I follow is a little different from the standard way of dealing with exceptions. Just because a select throws an exception doesn't necessarily mean the subscription is bad. The next event might be fine.
Note that in RX, when OnError is triggered it means the subscription must be terminated.
What I do is wrap my selects in a monadic Exceptional type to do the following
Exceptional<IDocumentMetadata> s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.SelectExceptional(ParseToMD);
If you just want to skip the bad ones
s.SelectMany(s=>s)
or you can project it like
var Exceptional<ProcessedDocumentType> =
s.Select(document => ProcessDocument(document))
If you need to extract the exception from the Exceptional type you can do this with properties
bool HasException
Exception Exception
To get the value you can access the property
T Value
However you should use Select and SelectMany if you are just operating on the good values and don't need the exceptions.
My implementation was based on
Exception or Either monad in C#
From your comments, I have to wonder if you are seeing the effect of using StartAsync rather than FromAsync. These methods differ in one important detail; the former runs once as soon as it is evaluated - i.e. it runs exactly once regardless of and before any number of subscribers. If there are no subscribers and it throws you will have an unobserved exception. Contrast with FromAsync which is called per subscriber on subscription.

Throwing a NPE at the start of method for error checking

So im preparing for interviews and in one of Gayle Laakmans career Cup videos a guy is writing a simple method that takes in an array and does something with it. She mentions his lack of error checking so he adds in this line like so:
public int max(int[] array) {
if (array == null)
throw new NullPointerException();
//method body
}
Is it correct to manually throw a NPE exception like this, this exception will get thrown anyway in the method body as it will use the array reference at some point.
A possible advantage to this i can see is that it separates input invalidation from the method logic being invalid and somehow creating a null reference. Otherwise it is a little confusing and maybe IllegalArgumentException would work better?
There's nothing wrong with throwing NullPointerException as soon as you enter the method instead of waiting to detect it after some processing has already been done. If the method is going to fail, it might as well fail fast.
Joshua Bloch's Effective Java recommends throwing NullPointerException over IllegalArgumentException in this situation (Item 60: Favor the use of standard exceptions).
If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException.
IllegalArgumentException should be thrown when an illegal non-null value is passed in.
Also have a look at java's own utility class java.util.Objects:
public static <T> T requireNonNull(T obj,
String message)
Checks that the specified object reference is not null and throws a customized NullPointerException if it is. This method is designed primarily for doing parameter validation in methods and constructors with multiple parameters, as demonstrated below:
public Foo(Bar bar, Baz baz) {
this.bar = Objects.requireNonNull(bar, "bar must not be null");
this.baz = Objects.requireNonNull(baz, "baz must not be null");
}
Type Parameters:
T - the type of the reference
Parameters:
obj - the object reference to check for nullity
message - detail message to be used in the event that a NullPointerException is thrown
Returns:
obj if not null
Throws:
NullPointerException - if obj is null
from https://docs.oracle.com/javase/7/docs/api/java/util/Objects.html
Conclusion
Whether or not you use this utility class is another question, but it definitely shows, that the team behind the Java language intended to use NullPointerException for these purposes.

Explicitly typing variables causes compiler to think an instance of a builtin type doesn't have a property, which it does

I narrowed the causes of an AS3 compiler error 1119 down to code that looks similar to this:
var test_inst:Number = 2.953;
trace(test_inst);
trace(test_inst.constructor);
I get the error "1119: Access of possibly undefined property constructor through a reference with static type Number."
Now if I omit the variable's type, I don't get that error:
var test_inst = 2.953;
trace(test_inst);
trace(test_inst.constructor);
it produces the expected output:
2.953
[class Number]
So what's the deal? I like explicitly typing variables, so is there any way to solve this error other than not providing the variable's type?
ok, this is a little hard to explain ... first of all, here is how it works:
var test_inst:Number = 2.953;
trace(test_inst);
trace((test_inst as Object).constructor);
to my understanding, this comes from the fact, that the property constructor comes from the ECMAScript-nature of ActionScript 3. It is an ECMAScript property of Object instances and is inherited through prototypes. From the strictly typed world of ActionScript 3 (which also uses a different inheritance mechanism), this property is thus not available.
greetz
back2dos
http://www.kirupa.com/forum/showpost.php?p=1951137&postcount=214
that has all the info you need :)
basically, trace(test_inst["constructor"]) will work.
Object(someobject).constructor will achieve the same thing -- and you don't have to deal with compiler issues.
Object(someinst) === someclass works as well.
dh

flex3 type casting

Does anyone know the real difference between the two ways of type casting in Flex 3?
var myObject1:MyObject = variable as MyObject;
var myObject2:MyObject = MyObject(variable);
I prefer to use the second method because it will throw an Error when type cast fails, whereas the first method will just return null. But are there any other differences? Perhaps any advantages to using the first method?
The second type of casting has different behaviour for top level(http://livedocs.adobe.com/flex/2/langref/) types, e.g. Array(obj) does not cast in the straightforward way you describe; it creates a new Array if possible from obj, even if obj is an Array.
I'm sure the times this would cause unexpected behaviour would be rare but I always use "as" for this reason. It means if I do
int(str)
I know it's a cast in the "attempt to convert" sense of the word not in the "I promise it is" sense.
ref: got some confirmation on this from http://raghuonflex.wordpress.com/2007/07/27/casting-vs-the-as-operator/
The as method returns null if cast fails.
The () method throws and error if the cast fails.
If the value of variable is not compatible with MyObject, myObject1 will contain null and you will be surprised by a null pointer error (1009 : cannot access a property or method of a null object reference.) somewhere later in the program when you try to access it. Where as if you are casting using the MyObject(variable) syntax, you will get a type coercion error (1034 : Type Coercion failed: cannot convert _ to _) at the same line itself - which is more helpful than getting a 1009 somewhere later and wondering what went wrong.
I think I read somewhere on this site that as is slighty faster than (), but I can't find the question again.
Beside that this question have been asked many times, you will find an more in-depth answer here.
I recently discovered the very useful [] tag when searching on StackOverflow, it allows to only search in questions tagged with the specified tag(s). So you could do a search like [actionscript-3] as vs cast. There are more search tips here: https://stackoverflow.com/search.
And no; the irony in that I can not find the question about performance and write about how to search is not lost on me ;)
I think as returns back the base class and not null when the casting fails and () throws an error.