Be careful how you call super()

Here’s something all ActionScript 3 developers should know about extending classes and how parent constructors are called:

If class B extends class A, does class B have to call super() in its constructor in order to instantiate the parent class? Nope. What happens if you don’t? The compiler inserts a call to the constructor for you. Usually.

The compiler just looks to see if you call super() at any point in your constructor. What if that call is inside of a conditional statement that evaluates to false? The default constructor won’t get inserted, and the parent classes’s constructor won’t get called. Why is that a problem? You may very well get null reference exceptions since class level variables are often initialized in constructors. What’s worse, you may only get them sometimes — only when your conditional statement evaluates to false.

Even if you determine that your code works whether super() is called or not, you still have to watch out. What if the implementation of the parent classes changes in the future? Code that used to work, and code that you could reasonably expect to continue working, may just break on you. I’ve actually seen this happen. It’s not pretty.

How do you avoid this problem? Either call super(), or don’t. Never put super() in a statement that may not execute, even if you find that your code works fine today since you never know what might happen to that parent class tomorrow.

6 Responses to Be careful how you call super()

  1. Dru Kepple says:

    What horror code were your reviewing that led to such a post? Putting a call to super() in a conditional has never even occurred to me, let alone something that I thought would be a good idea. If you’re extending a class…why wouldn’t you want to call super()?

  2. lee says:

    Never thought to put a constructor inside a conditional statement…didn’t think the compiler would allow it. Thanks for the heads up Christian!

  3. sascha/hdrs says:

    Isn’t putting super() in a conditional like … totally bad practice?!? If not I’m sure now it is.Christian says: Yes, it is bad practice, but there are instances where if *seems* reasonable (like when your constructor has optional arguments). Of course, now we all know there is never a good reason to actually do it, so it’s a moot argument.

  4. Erwin Verdonk says:

    Although I agree this behavior can be a pitfall, I think this really has more to do with the lack of knowledge of the programmer than with being careful on how you call super().Isn’t it logical that the parent constructor will not be automatically added when you’re already have a super() call somewhere inside your constructor, even when it is within a conditional statement? It’s basic stuff one should know about.Luckily this behavior also has it’s positive side. When I don’t want the parent constructor to be called – trust me, there are scenarios – you can omit it by placing super() within a conditional statement that will always return false :).In reply to Christian stating that there is never a good reason for optional arguments: I think optional arguments to a constructor is quite reasonable, since method overloading is not supported in ActionScript 3.Christian says: I didn’t mean to say that there’s never a good reason for optional constructor arguments. I agree with you that there certainly are. I meant there’s never a good reason not to call super() based on whether optional arguments are passed in (which is one good way to get yourself into this mess). In other words, it should always be safe to just call super. It’s interesting that you sometimes don’t want super to be called, though. Can you give an example?

  5. Erwin Verdonk says:

    I do agree with you that it is always safe to call super(). However you don’t always want this and therefor it is good you can prevent the super() to be called by default.Say for instance you have a class that has code in the constructor to initialize the instance etc. You have a need to extend this class in order to change some of its behavior. Methods and properties (get / set) you can override without calling its super, but what about the constructor? What of you want to change the whole initialization? In the constructor of the subclass you can do a rollback of the actions done in the parent constructor, but I don’t think that is always the best solution and can be a waste of CPU time. In that scenario I would like to prevent the super() to be called, just like I don’t always want to call the super method when overriding a method. I hope this is enough of an example :).

  6. Joseph says:

    Exactly the problem I faced! Thanks Christian.