0
votes

I've a strange issue. In Flash CS3 IDE, I linked a MovieClip to a SubSimba class. This class doesn't extend MovieClip (it has MovieClip package as its base) but, instead, it extends SuperSimba (that extends MovieClip). What happens? I instantiate SubSimba in my Flash project and it behaves as I if I called super() inside the SubSimba constructor: is there anyone here who understands why?

package {
    import flash.display.*;
    import flash.events.MouseEvent;

    public class SuperSimba extends MovieClip {
        public function SuperSimba() {
            trace('hi from SuperSimba');
        }
        private function doThis(evt:MouseEvent):void {
            // 
        }
    }
}


package {
    import flash.display.*;
    import flash.events.MouseEvent;

    public class SubSimba extends SuperSimba {
        public function SubSimba() {
            trace('hi from SubSimba');
        }
        private function doThis(evt:MouseEvent):void {
            //
        }
    }
}
2

2 Answers

2
votes

That is the default behavior.

Regarding why doThis is getting called on both subclass and super. That is because the super class does not have virtual keyword in the definition of the method.

On the SuperSimba class the definition of the method doThis() should be:

private virtual function doThis(evt:MouseEvent):void {

That way the subclass will only get called.

1
votes

I am not sure if I understood the question correctly, but super() in constructors is always called by default even if you don't explicitily state it. So during SubSimba's construction (either at the beginning or at the end, I am not sure) SuperSimba's constructor will be called.

EDIT:

To explain what we are talking about in comment to this answer.

You have to realize that private funcitons cannot be overriden and their scope is limited only to exactly the class you are in right now. So if you SuperSimba has doThis() and SubSimba has doThis() each of these doThis is considered separate function in separate scope.

So if in SubSimba you do addEventListener(SOME_EVENT, doThis); it will reference the SubSimba's doThis(). It has no idea that SuperSimba also has doThis funciton because it is Private and out of scope.

The same for SuperSimba. addEventListener(SOME_EVENT, doThis) in SuperSimba actually references the doThis declared in SuperSimba, because it has no idea of the one declared in SubSimba (because it is private).

In other words it is as if SuperSimba's doThis was completely different named function that SubSimba's. Private function is only available to the class it is residing in, and neither to its parents nor children. Read about access modifiers if you are confused.

Tutorial: how private and inheritance with defined constructors can anger you

You have two classes:

public class Super{
    public function Super(){ //THIS IS CONSTRUCTOR OF SUPER
        addEventListener(SOME_EVENT, doThis); 

        //This references doThis declared in Super
        //It cannot see doThis declared in Sub because it is both private
        //so it isn't overridden so even if you declare doThis in Sub it 
        //is completely different function
    }
    private function doThis(e:*):void{}
}

public class Sub extends Super{
    public function Super(){ //THIS IS CONSTRUCTOR OF SUB
        //There is this funky thing about flash constructors.
        //Event if you DON'T declare super() it will call it
        //without your knowledge. You can't avoid this really,
        //the only you could try is if (false) super() but I am not
        //sure this will work.
        
        //So, going further, Super's constructor is also called because
        //Sub extends this class. So by adding this event listener here
        //you end up with two listeners for the same event, like:
        //When SOME_EVENT happens call:
        //    doThis declared in Super,
        //    doThis declared in Sub

        addEventListener(SOME_EVENT, doThis)
    }
    private function doThis(e:*):void{}
}

So you can try overriding the automatic Super calling by using either if (false) super() or, more sophisticte, if (Math.random() > 100) super() but it's quite probable it won't work.

If you still don't understand what the problem is read: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7fcd.html and http://www.emanueleferonato.com/2009/08/26/undserstanding-as3-access-modifiers-public-internal-protected-private/