How do I implement the $ operator on a custom class in EK9?

← Operators and Expressions · Ref: Q910

Any EK9 class can define the $ operator to control how it converts to a String. The operator must be declared 'as pure', take no parameters, and return a String.

BASIC PATTERN

  MyClass
    name as String: String()
    operator $ as pure
      <- rtn as String: name

The $ operator returns whatever String representation makes sense for the type.

RULES FOR operator $
1. Must be declared 'as pure' — it extracts information without side effects
2. Must return String — the return type is always String
3. Takes no parameters — it operates on 'this' only
4. Can use backtick interpolation to build complex strings

USING BACKTICK IN operator $
You can use backtick interpolation inside the operator to combine fields:

  operator $ as pure
    <- rtn as String: `${name} (${$score})`

IMPLICIT USAGE

When you write `${myObject}` in a backtick string, the compiler calls the $ operator automatically. When you write $myObject as a standalone expression, it also calls the $ operator.

DEFAULT OPERATOR

If you use 'default operator' on a class, EK9 generates a default $ operator that combines all fields. You can override it with your own implementation.

See Q908 for $ basics. See Q242 for all conversion operators. See Q245 for complete custom type examples.

Example

defines module qa.operators.dollarcustom

  defines class

    Colour
      red as Integer: 0
      green as Integer: 0
      blue as Integer: 0

      Colour() as pure
        ->
          r as Integer
          g as Integer
          b as Integer
        this.red :=: r
        this.green :=: g
        this.blue :=: b

      operator $ as pure
        <- rtn as String: `rgb(${red}, ${green}, ${blue})`

      override operator ? as pure
        <- rtn as Boolean: red? and green? and blue?

    NamedColour
      colourName as String: String()
      colour as Colour: Colour()

      NamedColour()
        ->
          colourName as String
          colour as Colour
        this.colourName: colourName
        this.colour: colour

      operator $ as pure
        <- rtn as String: `${colourName}: ${colour}`

      override operator ? as pure
        <- rtn as Boolean: colourName? and colour?

  defines program

    CustomDollarDemo()
      stdout <- Stdout()

      // === Custom $ on Colour ===

      red <- Colour(255, 0, 0)
      stdout.println($red)

      // === Custom $ on NamedColour (delegates to Colour.$) ===

      namedRed <- NamedColour("Red", red)
      stdout.println($namedRed)

      // === $ inside backtick interpolation ===

      blue <- Colour(0, 0, 255)
      stdout.println(`Blue is: ${blue}`)

      // === Multiple custom types ===

      green <- Colour(0, 255, 0)
      namedGreen <- NamedColour("Green", green)
      stdout.println(`Colour: ${namedGreen}`)

Common mistakes

E07500 — The $ operator must be declared 'as pure' because it extracts information without side effects. Omitting 'as pure' triggers E07500. See ek9 -h E07500 for details.

Incorrect:

operator $

Correct:

operator $ as pure
Other ways to ask this
  • How do I define _string() for my type in EK9?
  • How does a class customize its String representation in EK9?
  • How do I override the $ operator in EK9?

Coming from another language?

Java: override toString() method. Python: define __str__() or __repr__(). Rust: implement Display trait. Go: define String() method. Kotlin: override toString(). JavaScript: define toString() method. EK9: define 'operator $ as pure' returning String.

Keywords: conversion, operator, custom, string, dollar, override, class, pure