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 own operators BEFORE it; 'default operator' then generates only the ones you did not write. The 'override' keyword is required on operator ? because every class inherits ? from its base type.

WHAT GOES WRONG:

  default operator
  operator ? as pure           WRONG: E01086, nothing may follow 'default operator'
    <- rtn as Boolean: host?

Adding 'override' there does not help - it is still E01086. Move the operator above 'default operator'. And placed above it WITHOUT 'override', operator ? is E05120 ('override' required).

APPROACH 3 - no default, all manual:

  override operator ? as pure  ? is inherited from the base type, so override is still required
    <- rtn as Boolean: host?
  operator $ as pure           no override - no parent declares $
    <- rtn as String: host

See Q1068 for the 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 — A manual operator ? placed before 'default operator' still replaces the ? every class inherits from its base type, so it needs 'override'. (Placing it AFTER 'default operator' is the syntax error E01086, with or without 'override'.)

Incorrect:

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

Correct:

      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 E01086 when I put operator ? after default operator
  • Should I use default operator or write my own operators?

Coming from another language?

Java: @Override on any method you override. EK9: 'override' is mandatory on an operator a parent type already has (always for ?), and 'default operator' must come last, after your own operators (E01086 otherwise).

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