Search code examples
actionscript-3inheritanceoverridingsubclasssuperclass

AS3: Calling superclass method instead of subclass instance's override?


Let's say we have superclass A and subclass B:

public class A {
    public function f() {...}
}

public class B extends A {
    override public function f() {...}
}

Superclass A has a method called f, and subclass B has an override for f. Now I have an instance of class B:

var b:B = new B();

Is it impossible to call b's superclass version of f, by doing something like b.super.f()? Without writing a method for B that explicitly calls super.f();


Solution

  • Short answer: Kind of, but it's not fun

    Long answer: I originally thought that it would be possible using the Function object and either apply() or call(), but the even though the docs (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Function.html#apply()) say that you can pass another object, it doesn't work, it's always bounds to the declared class.

    ...
    public function foo():void
    {
        trace( this );
    }
    ...
    
    var func:Function = a.foo;
    func.apply( b ); // traces a
    

    After stumbling around a bit, I came across this SO answer (Function.apply not using thisArg parameter), which explains why this isn't working (tldr; it's because methods are bounds to their instances on creation).

    It's possible to hack around this using prototype though. You just need to declare your class like this:

    public dynamic class A 
    {
        prototype.foo = function():void
        {
            trace( this );
        }       
    }
    

    NOTE the function declaration style and the dynamic property on the class. The foo() function won't be bound on creation, so you can call it like:

    var func:Function = a.foo;
    func.apply( a ); // traces a
    func.apply( b ); // traces b
    

    This works even if B declares another method called foo.

    In short, to get it to work/downsides:

    • You need to make your classes dynamic (thus bigger, and able to add whatever param you wanted)
    • You need to hack the declaration of the function itself
    • You need access to a base class Function object (though you can just call ( new A ).foo)
    • You don't get code completion

    All in all, it's probably easier to create a method on B to expose the A functionality (or if you find yourself need to call this from outside, just break it off to a dedicated function, where it's treated like any other public func)