Why can't extend DisplayObject then instantiate - actionscript-3

The DisplayObject class can be extended but the extended class cannot be instantiated.
Class:
package{
import flash.display.DisplayObject;
class Extended extends DisplayObject{
public function Extended(){
super()
}
}
}
Main timeline:
var e:Extended=new Extended();
addChild(e);
Error:
ArgumentError: Error #2012: Extended$ class cannot be instantiated.

Please read the documentation of the DisplayObject class:
The DisplayObject class itself does not include any APIs for rendering content onscreen. For that reason, if you want create a custom subclass of the DisplayObject class, you will want to extend one of its subclasses that do have APIs for rendering content onscreen, such as the Shape, Sprite, Bitmap, SimpleButton, TextField, or MovieClip class.

Related

Error when overriding constructor of extended class

I found a quite strange problem while making two classes in AS3. Let's call them ParentClass and ChildClass. In order to make both of them you need a Sprite object, then the ParentClass makes it visible in the stage. ChildClass inherits the ParentClass, too.
ParentClass.as:
package myStudio.basic {
import flash.display.MovieClip;
import flash.display.Sprite;
public dynamic class ParentClass extends MovieClip {
public function ParentClass(mc:Sprite=null) {
addChild(mc);
}
}
}
ChildClass.as:
package myStudio.containers {
import myStudio.basic.ParentClass;
import flash.display.MovieClip;
import flash.display.Sprite;
public class ChildClass extends ParentClass {
public function ChildClass(mc:Sprite=null) {
addChild(mc);
}
}
}
Then, I write this code on Frame 1, Layer Actions of the FLA file:
var mc:MovieClip = new childMC;
var vig:ChildClass = new ChildClass(mc);
addChild(vig);
However, I got run-time error #2007:
TypeError: Error #2007: The value of the parameter child must not be null.
at flash.display::DisplayObjectContainer/addChild()
at myStudio.basic::ParentClass()
at myStudio.containers::ChildClass()
at myStudioComicAnimator_fla::MainTimeline/frame1()
I tried overriding the ChildClass constructor function, but it still doesn't work.
So here's my question: Is there another workaround to solve this problem?
The reason for that is that you are not calling super. You can check what's happening in the error stack (down to top):
you instantiate ChildClass, and you pass the previously created childMC to the constructor
ChildClass extends ParentClass, so when instantiated it always calls the constructor
the constructor of ParentClass tries to add something as a child
The problem is that you cannot add null as a child. But because the constructor is called internally, there is no param that is being passed to it. so mc variable is always null. But as we said - null cannot be added.
Use the super by yourself:
public function ChildClass(mc:Sprite=null) {
super(mc);
}
This way the ParentClass will get reference to the mc object and will be able to add it.
Another option is not to use addChild in the ParentClass, but only in ChildClass. Then it doesn't matter if you pass anything to super, or even if you are calling super at all.
Edit: I forgot to say that this is not a bug, but a standard behavior and works exactly like it should work. The reason for this is that each class can have a whole different override of the constructor. It can take more or less parameters, so the chain for calling parent's constructor is your job to handle.

Call custom method as Display Object AS3

I have a class which extends MovieClip. This class has an update() function which needs to be called every new frame with the deltaTime in the arguments. This works if the class has been declared but not if it has just been added to the display list.
Code in the main class:
package packageFoo{
import flash.display.MovieClip;
import packageFoo.customMovieclip;
public class Main extends MovieClip{
public function Main():void{
var testMc:customMovieClip = new customMovieClip();
addChild(testMc);
testMc.update(dt);
}
}
}
This outputs the correct values where as if I just added it without referencing it:
package packageFoo{
import flash.display.MovieClip;
import packageFoo.customMovieclip;
public class Main extends MovieClip{
public function Main():void{
addChild(new customMovieclip());
this.getChildAt(0).update(dt);
}
}
}
This makes the compile time error: 1061: Call to a possibly undefined method update through a reference with static type flash.display:DisplayObject.
I can't really reference the 'customMovieclip's because I am wanting multiple ones.
It looks like this.getChildAt(0) is not customMovieClip. This can arise if your Main has pre-places components at design time. To check, do trace(this.numChildren) as the first line of Main() constructor. And also, to address any subclass methods properly, you need to typecast your DisplayObject returned by getChildAt() to a proper type.
(this.getChildAt(0) as customMovieClip).update(dt);
Still, using a class-wide variable is better if you want to address that custom MC in more than one function of main class.
If you're trying to avoid a reference to the custom class in the document class, you can call it like this:
this.getChildAt(0)["update"](dt);

super() in Flash Builder. WHY?

Every time I start a new actionscript class in Flash Builder it starts off the constructor with a line
super()
I have never seen this before, and it seems to have no purpose. Deleting it results in the exact same movie.
Why is it inserted into my new class and what does it do?
super() calls the constructor from the class that you're inheriting (extending).
If your inherited (base) class has no required parameters in it's constructor, you can omit it all together and flash will automatically call it before your constructor code.
You can call other functions (that are public or protected) from your base class by using the super keyword:
super.myBaseClassMethod(); //would call the method 'myBaseClassMethod' from your base class even if you had an overriden method with in this class
EXAMPLE:
package {
public class BaseClass {
public function BaseClass(){
trace("Base Class Constructed");
}
public function someBaseMethod():void {
trace("some method called from base");
}
}
}
package {
public class MyClass extends BaseClass { //this class is extending the class above
public function MyClass():void {
trace("My Class constructed");
super();
someBaseMethod();
super.someBaseMethod();
}
override public function someBaseMethod():void {
trace("Override");
}
}
}
So if you do this:
var tmp:MyClass = new MyClass();
You will get:
"My Class constructed"
"Base Class Constructed"
"override"
"some method called from base"
If you omit super(), it will be:
"Base Class Constructed"
"My Class constructed"
"override"
"some method called from base"
As a part of inheritance, super invokes the superclass or parent version of a method or constructor.
Invokes the superclass or parent version of a method or constructor.
When used within the body of a class constructor, the super()
statement invokes the superclass version of the constructor. The call
to the superclass constructor must have the correct number of
arguments. Note that the superclass constructor is always called,
whether or not you call it explicitly. If you do not explicitly call
it, a call with no arguments is automatically inserted before the
first statement in the subclass constructor body. This means that if
you define a constructor function in a subclass, and the superclass
constructor takes one or more arguments, you must explicitly call the
superclass constructor with the correct number of arguments or an
error will occur. The call to the superclass constructor, however,
does not need to be the first statement in your subclass constructor,
as was required in ActionScript 2.0.
When used in the body of an instance method, super can be used with
the dot (.) operator to invoke the superclass version of a method and
can optionally pass arguments (arg1 ... argN) to the superclass
method. This is useful for creating subclass methods that not only add
additional behavior to superclass methods, but also invoke the
superclass methods to perform their original behavior.
You cannot use the super statement in a static method.
In ActionScript, classes can extend other base classes not marked as final.
For example, MovieClip inheritance is as follows:
Sprite > DisplayObjectContainer > InteractiveObject > DisplayObject > EventDispatcher > Object
By invoking super(), you control when parent constructors are called.
package
{
import flash.display.MovieClip;
public class ExampleMovieClip extends MovieClip
{
public function ExampleMovieClip()
{
super(); // MovieClip's constructor is called
}
}
}

AS3, Flash - Call a function in a class?

I am trying to call a function which is set inside a class..
How can I call that?
Here is my source, and I would like to call 'processLogin' from outside this class.
Link to source: http://pastebin.com/aFygyXKZ
You can create a new instance of your class main.
Try
var m:main = new main();
m.processLogin();
Also, AS3 best practices state that classes should begin with an Uppercase letter.
You also should extend Sprite instead of MovieClip for DisplayObject classes that do not need timeline functionality.
If you know you are only going to have one instance of the class main in your application, what you can do is:
Implement class main as a singleton class, in which case you
can access the processLogin method using
main.getInstance().processLogin or
Just add a public static
variable to your main class containing the instance of your main
class. In this instance your code would look something like:
package actions {
import flash.display.MovieClip;
import flash.events.*;
import flash.net.*;
import flash.text.*;
public static var instance:main;
public function main(){
instance = this;
}
//The rest of your main class code...
}
That way, you can access your processLogin function using main.instance.processLogin().
However, if your application is set to possibly have more than one instance of your main class, then the best approach would be to instantiate main and use that instance, as f-a suggested.

Adobe Air - Dispatch event with parameter

How to pass the addChild(event.target.loader) through a dispatch event from the class to the main timeline?
package scraps
{
...
public class FileScrap extends Scrap
{
...
private function loadImage(event:Event):void{
addChild(event.target.loader);
}
Thanks
You can create a custom event class that extends flash.events.Event and have the DisplayObject that gets loaded sent as a property of that event. In that case FileScrap will need to inherit from EventDispatcher or implement IEventDispatcher.
You could also just dispatch a generic event called IMAGE_LOADED or something like that, and have the main class poll a public method in scraps to get the image whenever it receives the event.