Can I use default operator and also define my own operator ? on the same class?

← Override Mechanics · Ref: Q1069

Yes, but you must choose one of two approaches:

APPROACH 1 — default operator only (simplest):

  defines class
    Config
      host as String: String()
      port as Integer: 0
      default operator

This generates ?, $, ==, <>, <=>, #? from all fields. Use this when field-by-field behaviour is correct.

APPROACH 2 — custom override then default operator last:

  defines class
    Config
      host as String: String()
      port as Integer: 0
      override operator ? as pure
        <- rtn as Boolean: host?
      default operator

IMPORTANT: 'default operator' must be the LAST item in the class body. Put your override operators BEFORE it. The 'override' keyword is required because default operator generates ? first.

WHAT CAUSES E02030:

  default operator
  operator ? as pure           WRONG: duplicate, missing override
    <- rtn as Boolean: host?

The fix is to add 'override':

  default operator
  override operator ? as pure  CORRECT: overrides the generated one
    <- rtn as Boolean: host?

APPROACH 3 — no default, all manual:

  operator ? as pure           No override needed — nothing to override
    <- rtn as Boolean: host?
  operator $ as pure
    <- rtn as String: host

Wait — operator ? DOES need override even without default operator, because every class inherits ? from its base type. So always use 'override operator ?'.

for E05120 fix. See Q116 for what default operator generates. See Q1055 for default vs manual.

Example

defines module qa.overridemechanics.defaultwithoverride

  defines class

    //APPROACH 1: default operator only
    SimpleConfig
      host as String: String()
      port as Integer: 0

      SimpleConfig()
        ->
          host as String
          port as Integer
        this.host :=: host
        this.port :=: port

      default operator

    //APPROACH 2: custom override then default operator last
    SmartConfig
      host as String: String()
      port as Integer: 0

      SmartConfig()
        ->
          host as String
          port as Integer
        this.host :=: host
        this.port :=: port

      //Custom ? before default operator
      override operator ? as pure
        <- rtn as Boolean: host?

      default operator

  defines program

    DefaultOverrideDemo()
      stdout <- Stdout()

      simple <- SimpleConfig("localhost", 8080)
      stdout.println(`Simple set: ${simple?}`)
      stdout.println(`Simple: ${simple}`)

      smart <- SmartConfig("localhost", 8080)
      stdout.println(`Smart set: ${smart?}`)
      stdout.println(`Smart: ${smart}`)

      //SmartConfig only checks host, not port
      partialSmart <- SmartConfig(String(), 8080)
      stdout.println(`Partial set: ${partialSmart?}`)

Common mistakes

E05120 — When using default operator alongside a manual operator ?, add 'override' to the manual one. Default operator generates ? first, your definition overrides it.

Incorrect:

      default operator
      operator ? as pure
        <- rtn as Boolean: host?

Correct:

default operator
      override operator ? as pure
        <- rtn as Boolean: host?
Other ways to ask this
  • How do I mix default operator with a custom isSet check?
  • I get E02030 duplicate operator when I use default operator and operator ?
  • Should I use default operator or write my own operators?

Coming from another language?

Java: @Override on any method you override. EK9: override keyword mandatory on operators inherited from parent or generated by default operator.

Keywords: operator, duplicate, E05120, override, combine, E02030, default