super() in Flash Builder. WHY? - actionscript-3

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
}
}
}

Related

Why Powermock PrepareForTest prevent mock inject?

My code is like below:
public class RealWorldBoImpl extends AbstractBoImpl<T> implements SomeBo{}
And
#RunWith(PowerMockRunner.class)
#PrepareForTest({RealWorldBoImpl.class})
public class RealWorldBoImplTest {
#InjectMocks
private RealWorldBoImpl realWorldBo;
#Mock
private RealWorldDAO realWorldDAO;
#Test
public void changeStatusMainSubString() throws Exception {
long id = 1L;
}
In this case, realWorldDAO cannot inject to realWorldBo. But when I delete PrepareForTest, it works.
I also tried other classes, they worked well. It seems RealWorldBoImpl is special that when prepare for it, it will not inject mocks correctly.
I debugged this code, and found that, in org.mockito.internal.util.reflection.FieldInitializer#checkParameterized, constructor.getParameterTypes() is not empty and has a constructor with the class IndicateReloadClass.
private void checkParameterized(Constructor<?> constructor, Field field) {
if(constructor.getParameterTypes().length == 0) {
throw new MockitoException("the field " + field.getName() + " of type " + field.getType() + " has no parameterized constructor");
}
}
But I don't know what's special with RealWorldBoImpl. It just extends a parent class and implements an interface. Does it matter?
When PowerMock prepares a class which has a superclass other than Object it adds a constructor to the class which takes an argument of type org.powermock.core.IndicateReloadClass.
Why PowerMock does this? PowerMock implements superclass constructor suppression through this mechanism.
In your case because RealWorldBoImpl derives from AbstractBoImpl PowerMock adds the following constructors to RealWorldBoImpl, AbstractBoImpl classes:
public RealWorldBoImpl(IndicateReloadClass var1) {
super(var1);
}
public AbstractBoImpl(IndicateReloadClass var1) {
super(); //assuming the parent class is Object otherwise super(var1)
}
and changes the default no-arg constructor of RealWorldBoImpl to the following:
public RealWorldBoImpl() {
Object var1 = MockGateway.constructorCall(Desc.getClazz("org.example.RealWorldBoImpl"),
new Object[0], Desc.getParams("()V"));
if (var1 != MockGateway.PROCEED) {
super((IndicateReloadClass)null);
} else {
super();
}
}
That was the PowerMock part now let's get to the Mockito part.
Mockito has two injection strategies (MockInjectionStrategy): ConstructorInjection and PropertyAndSetterInjection.
ConstructorInjection uses constructor to inject mocks and is used if the injectee has at least one non-default constructor (a constructor that takes at least an argument). In case the injectee has only a no-arg constructor, Mockito uses PropertyAndSetterInjection which uses setter method and if there is no setter method it injects the mocks directly by setting the field's value through reflection.
In your case when you prepare RealWorldBoImpl class you have a constructor with one argument and Mockito uses ConstructorInjection to inject mocks to your object through the constructor that was added by PowerMock (and as there's no mock of type IndicateReloadClass, Mockito passes null to the constructor but that does not matter as the constructor does nothing) and as a result no mocks are injected.
So how can you solve the problem? If you have more than one mock to inject, then add a constructor to the injectee class with as many arguments as the number of mocks you want to inject. As long as you have a constructor with more than one argument, injection will work otherwise your injectee class should have Object as it superclass.
If you have only one mock to inject, you can add a dummy argument to the constructor to make Mockito choose your constructor over the one added by PowerMock:
public RealWorldBoImpl(RealWorldDAO realWorldDAO, String dummy) {
this.realWorldDAO = realWorldDAO;
}

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.

Select a extern class to start with

my problem is pretty hard to describe and to google for <_< so ill give it a try here.
ihave my main.as, char.as, enemy.as, classes
my main was the stage of course.... it worked pretty well, but now that my main is extern too, it wont be called anymore...
it calls: char, enemy(which is a sub class of char) and then the empty stage but it never calls my main.as which should be called first...
also it never calls any constructors...how can i tell flash to start with my main.as?
i hope you got it, the code is probably to much to post here :P
If get you right.. you have to put super() calls to extended classes.
So for example in enemy class constructor:
public class enemy extends char {
function enemy() {
super(); // calls "char" class constructor
}
}
and if you have params in your constructors:
public class enemy extends char {
function enemy(param1: String, param2:String) {
super(param1, param2); // calls "char" class constructor
}
}
Overriding methods:
override public function doSome():void {
super.doSome(); // call parent class
}
and to make flash start with your main class - select your FLA file stage in flash (professional) and from the right side panel (properties) set Class to your main class (for example: com.myApp.Main).

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);

Override function in CS5 IDE -> Timeline -> Framescript

I have a baseclasse which implements an interface. I use this baseclass as my "template" ( read: Semantics, i'm not talking about Java/C++ Templates).
In my Flash CS5 IDE I want to override these interface methods.
Yes they are implemented in the base class, but trying to override them in framescript throws me( YES this might probably not be a clean design):
Symbol 'GameTest', Layer 'Layer 1', Frame 1, Line 1 1024:
Overriding a function that is not marked for override.
I don't exactly know in what scope framescripts work. And by framscript I just mean in the timeline frame 1.
in my base class:
public class MiniGameTemplate extends MovieClip implements IMiniGame
{
public function MiniGameTemplate()
{
}
public function update():void
{
}
}
In my Library object's first frame:
override function update():void
{
}
I'm using actionscript linkage to inherit my library object from the base class.
If I clear the framescript, it runs fine. No error.
When overriding a method, you must structure the overriding method exactly like the original. In this case you've missed the public access modifier statement.
Solution:
override public function update():void {
}