When is an explicit super() call required?

← Constructor Delegation · Ref: Q584

super() is only needed when you want the parent initialised from arguments. If the parent has a no-arg constructor (declared, or the one EK9 synthesises), EK9 implicitly calls it. E05040 fires if you call super() or use super.member in a class without an explicit parent class. E05080 is the 'inappropriate use of super' error, for example super(...) used as a property initialiser.

WHEN SUPER() IS NEEDED

When the parent's only declared constructor takes parameters, EK9 still synthesises a public no-arg constructor for it. A child constructor that omits super() therefore compiles - the implicit super() reaches that no-arg constructor - but the parent's properties are left unset (here entityName). Call super(entityName) to give the parent its value. Only when the parent's no-arg constructor is private is omitting super() a compile error (E07176/E07177).

WHEN SUPER() IS IMPLICIT

If the parent has a no-arg constructor (or a default constructor), and the child constructor does not explicitly call super(), the parent no-arg constructor is called implicitly.

E05040: NO EXPLICIT PARENT

If you call super() in a class that does not explicitly extend another class, the compiler reports E05040.

SUPER MEMBER ACCESS WITHOUT A PARENT

Using the 'super' keyword for member access ('super.entityName()') in a class that does not extend another is also E05040.

E05080: INAPPROPRIATE USE OF SUPER

super(...) written as a property initialiser, for example 'petName as String: super("x")', is reported as E05080.

See Q580 for this() delegation. See Q581 for super() basics. See Q582 for delegation order. See Q587 for multi-level constructor hierarchies.

Example

defines module qa.constructor.missingsuper

  defines class

    //Parent with required parameter: child MUST call super()
    NamedEntity as open
      entityName <- String()

      NamedEntity()
        -> entityName as String
        this.entityName: entityName

      entityName() as pure
        <- rtn as String: entityName

      default operator ?

    //Child calls super(entityName) so the parent is given its value;
    //omitting it would still compile but leave entityName unset
    TaggedEntity extends NamedEntity
      tag <- String()

      TaggedEntity()
        ->
          entityName as String
          tag as String
        super(entityName)
        this.tag: tag

      tag() as pure
        <- rtn as String: tag

      default operator ?

    //Parent with default constructor: super() is implicit
    SimpleBase as open
      default SimpleBase()

      baseLabel() as pure
        <- rtn as String: "simple"

      default operator ?

    //Child does not need explicit super() call
    SimpleDerived extends SimpleBase
      derivedLabel <- String()

      SimpleDerived()
        -> derivedLabel as String
        //No super() needed: SimpleBase() is called implicitly
        this.derivedLabel: derivedLabel

      derivedLabel() as pure
        <- rtn as String: derivedLabel

      default operator ?

  defines program

    MissingSuperCallDemo()
      stdout <- Stdout()

      //Explicit super() required
      tagged <- TaggedEntity("Server", "production")
      stdout.println(`${tagged.entityName()}: ${tagged.tag()}`)

      //Implicit super() (no-arg parent)
      simple <- SimpleDerived("extra")
      stdout.println(`${simple.baseLabel()}: ${simple.derivedLabel()}`)

Common mistakes

E50060 — String has no toUpperCase() method in EK9. Use upperCase() instead. See ek9 -h E50060 for details.

Incorrect:

stdout.println(tagged.entityName().toUpperCase())

Correct:

stdout.println(`${tagged.entityName()}: ${tagged.tag()}`)

E05050 — The super() call must be the first statement. The parent must be fully initialized before the child assigns its own fields. See ek9 -h E05050 for details.

Incorrect:

TaggedEntity()
        ->
          entityName as String
          tag as String
        this.tag: tag
        super(entityName)

Correct:

TaggedEntity()
        ->
          entityName as String
          tag as String
        super(entityName)
        this.tag: tag
Other ways to ask this
  • What is E05040 super without explicit parent?
  • When must I call super() in a constructor?
  • Does EK9 have implicit super() calls?

Coming from another language?

Java: implicit super() if parent has no-arg constructor. Python: must explicitly call super().__init__(). Kotlin: delegation in class header. C#: implicit base() if no-arg exists. EK9: implicit no-arg super(), explicit required when parent needs arguments, E05040 for super in a parentless class, E05080 for super(...) as a property initialiser.

Keywords: super, E05080, constructor, explicit, this, delegation, implicit, parent, missing, E05040