How do I override operators in EK9?

← Override Mechanics · Ref: Q577

Operators follow the same override rules as methods. When a parent class defines an operator, the child must use 'override operator' to replace it.

OVERRIDE OPERATOR ? (ISSET)

The most commonly overridden operator is '?'. Since all types inherit operator ? from the base, custom classes use 'override operator ?':

  override operator ? as pure
    <- rtn as Boolean: name?

OVERRIDE COMPARISON

If a parent defines operator <=>, the child uses 'override operator <=>':

  override operator <=> as pure
    -> other as MyType
    <- rtn as Integer: ...

OVERRIDE STRING

If a parent defines operator $, the child overrides it:

  override operator $ as pure
    <- rtn as String: ...

DEFAULT OPERATOR

The 'default operator ?' shorthand can be used in any class. When a parent already has operator ?, using 'default operator ?' in the child effectively overrides it with the default implementation.

See Q570 for override basics. See Q245 for custom type operators. See Q568 for pure operators. See Q96 for class operators.

Example

defines module qa.override.operator

  defines class

    Measurement as open
      amount <- 0.0

      Measurement()
        -> amount as Float
        this.amount: amount

      amount() as pure
        <- rtn as Float: amount

      operator <=> as pure
        -> other as Measurement
        <- rtn as Integer: amount <=> other.amount

      default operator ==

      operator $ as pure
        <- rtn as String: $amount

      operator #? as pure
        <- rtn as Integer: #? amount

      override operator ? as pure
        <- rtn as Boolean: amount?

    //Child overrides operators
    Weight extends Measurement
      Weight()
        -> amount as Float
        super(amount)

      //Override string representation
      override operator $ as pure
        <- rtn as String: `${amount()} kg`

      default operator ?

    Length extends Measurement
      Length()
        -> amount as Float
        super(amount)

      override operator $ as pure
        <- rtn as String: `${amount()} m`

      default operator ?

  defines program

    OverrideOperatorDemo()
      stdout <- Stdout()

      weight <- Weight(75.5)
      stdout.println(`Weight: ${weight}`)

      lengthVal <- Length(1.82)
      stdout.println(`Length: ${lengthVal}`)

      //Comparison works through parent operator
      stdout.println(`Compare: ${weight <=> Weight(80.0)}`)
      stdout.println(`Equal: ${weight == Weight(75.5)}`)

Common mistakes

E05120 — When the parent class defines operator $, the child must use override operator $ to replace it. Omitting override on operator overrides triggers shadowing detection. See ek9 -h E05120 for details.

Incorrect:

operator $ as pure

Correct:

override operator $ as pure

E07500 — The parent operator $ is pure, so the child override must also be pure. Removing purity from the override violates the purity contract. See ek9 -h E07500 for details.

Incorrect:

override operator $

Correct:

override operator $ as pure
Other ways to ask this
  • How do I override operator ? in a child class?
  • What is 'override operator' syntax?
  • Must I use 'override' for operators too?

Coming from another language?

Java: no operator overloading. Kotlin: operator overloading exists, override keyword applies. C#: operator overloading but no inheritance override. EK9: operators follow identical override rules to methods, 'override operator' syntax.

Keywords: operator, inherit, default, override, string, comparison, child, open, isSet, virtual, abstract