Super need not apply, nor call

Dude, is this a bug in AS2? I’m probably doing it wrong.

In the main timeline, I can do:

function Mammal(target)
{
        this.target = target;
}

function Cow(t)
{
        super.apply(this, [t]); // doesn't work
        super.apply(super, [t]); // doesn't work
        super.call(this, t); // doesn't work
        super.call(super, t); // doesn't work
}
Cow.prototype = new Mammal();

It doesn’t even compile in AS2:

class Mammal extends Cow
{
        function Mammal(t)
        {
                super.apply(this, [t]); // says there is no apply method
                super.call(this, t); // says there is no call method
        }
}

I’m guessing this is because inside the constructor, it’s scoped to the function vs. “this”, where this is the class.

Typically, I’ll do:

function MyClass()
{
        init.apply(this, arguments);
}

So if the init method has a lot of arguments, I don’t have to type them out 3 times; twice in the constructor, and then again in the init. I figured I could just bypass init, and use super… but I guess he’s weird…? I’m confused.

11 Replies to “Super need not apply, nor call”

  1. When you use classes in AS2, the super constructor actually gets called automatically whether you want it to or not. This can be annoying so in my base class the constructor just calls a function called ‘constructor’. That way subclasses can order instantiation to their liking

    Btw, I got that AS2 little example of yours to compile just fine…

  2. That’s jacked…

    Ok, first off, I was under the impression, when compiling for Flash 6, that the constructor got called twice whether using AS1 or AS2; that was the whole point of:

    if(this._name == undefined){
    return false;
    }

    Secondly, I know the constructor gets called automatically if you use the component framework (inheriting from UIObject/UIComponent)… but what if your not?

  3. Yo J – even if you’re not using the framework, anytime you extend a class, “super” is automatically called as the first line of the constructor, whether you put it there or not. It’s one of those OOP things…

  4. super is different. I think there is a work around, but workarounds aren’t good. I can’t remember.. maybe it was this.constructor.prototype.constructor.apply. but as you can see that is nasty. It is better to reevaluate your design than to try and rig things up.

  5. I realized that exact thing this week when I noticed that the super call wasn’t necessary to access the props and method of the class i was extending. Screwed me right up – cos i tend to do the same thing – use the apply in the init method.

    Flash just kinda inserts the super for you – but if you need to pass a param/arg then i *think* you need to insert it yourself.

  6. Yes, darron is right. “super” does get called. Unfortunately it happens the wrong way. Without passing any parameters from the subclass.

    That’s why, if you want to pass any parameters to the superclass constructor you have to resort to an artifice like this:

    super.constructor.apply(this, arguments);

    Which for your example is equivalent with:

    Cow.prototype.Mammal.constructor(arguments);

    Btw, it should be:

    class Cow extends Mammal

    and not the other way ;)

  7. Uhmmmm, i don’t get it? What are you trying to do? Just pass aruments to the parent constructor?

    Does this not do the trick?

    function a(target){
    this.target = target;
    }

    function b(target){
    super(target);
    }

    b.prototype = new a();

    b.prototype.getTarget = function(){
    trace(this.target);
    };

    c = new b(“Foo”);
    c.getTarget();

  8. From what I gathered, Jester was trying to use apply or call, because he didn’t want to handle the constructor parameters individually when calling the super constructor, which is very convenient any many instances.

  9. Yep.

    function Person(name, age, gender)
    {
    init(name, age, gender);
    }

    function init(name, age, gender)
    {
    this.name = name;
    this.age = age;
    this.gender = gender;
    }

    vs.

    function Person()
    {
    init.apply(this, arguments);
    }

    function init(name, age, gender)
    {
    this.name = name;
    this.age = age;
    this.gender = gender;
    }

    That way, I only I need to write them once!

  10. Why not initialize non visual data in the constructor and only leave visual prop inits to the init? If you had a class that could exist beyond the frame of the visual, then you could maintain non visual data and then just reinitialize your visuals when it came into existence again. Object creation is a real process worker. You can create creation factories that reuse objects and lessen the need of constant instantiation.

  11. ok gotcha, minor disconnect.

    just to point out super.constructor.apply will only ever target the top of your tree. So if you have a GrandParent, Parent and Child class if you apply super.constructor in child GrandParents constructor is applied and not Parents!

    You could always define your own constructor type variable i.e.:

    function GrandParent(){}

    function Parent(){
    this.parent = this;
    }

    Parent.prototype = new GrandParent();

    function Child(){
    this.parent.apply(foo,bar);
    }

    Child.prototype = new Parent();

    However, in either case I think if you where to come back to your code a few months later it wouldn?t be as readable imo.

    -erik

Comments are closed.