Write an EK9 class with comparison operators so I can sort a list of them.

← Functions and Methods · Ref: Q1065

Define the <=> (spaceship) operator, then derive <, >, <=, >= from it. Add #? for hashcode and $ for string display.

defines class

  Product
    productName as String: String()
    price as Float: 0.0
    Product()
      -> productName as String, price as Float
      this.productName :=: productName
      this.price :=: price
    operator <=> as pure
      -> other as Product
      <- rtn as Integer: price <=> other.price
    operator < as pure
      -> other as Product
      <- rtn as Boolean: (this <=> other) < 0
    operator > as pure
      -> other as Product
      <- rtn as Boolean: (this <=> other) > 0
    operator $ as pure
      <- rtn as String: `${productName}: ${price}`

Now you can sort:

  cat products | sort > stdout

See Q1049 for comparison on records. See Q1047 for hashcode. See Q1055 for default operator.

Example

defines module qa.functions.writesortableclass

  defines class

    Product
      productName as String: String()
      price as Float: 0.0

      default private Product()

      Product()
        ->
          productName as String
          price as Float
        this.productName :=: productName
        this.price :=: price

      operator <=> as pure
        -> other as Product
        <- rtn as Integer: price <=> other.price

      operator < as pure
        -> other as Product
        <- rtn as Boolean: (this <=> other) < 0

      operator > as pure
        -> other as Product
        <- rtn as Boolean: (this <=> other) > 0

      operator <= as pure
        -> other as Product
        <- rtn as Boolean: (this <=> other) <= 0

      operator >= as pure
        -> other as Product
        <- rtn as Boolean: (this <=> other) >= 0

      operator #? as pure
        <- rtn as Integer: #?productName + #?price

      override operator ? as pure
        <- rtn as Boolean: productName? and price?

      operator $ as pure
        <- rtn as String: `${productName}: ${price}`

  defines program

    SortableClassDemo()
      stdout <- Stdout()

      products <- [
        Product("Widget", 9.99),
        Product("Gadget", 24.99),
        Product("Doohickey", 4.99)
      ]

      //Sort by price (uses <=> operator)
      stdout.println("Sorted by price:")
      cat products | sort > stdout

      //Get cheapest
      cheapest <- Product("Widget", 9.99) <? Product("Gadget", 24.99)
      stdout.println(`Cheapest: ${cheapest}`)

Common mistakes

E01010 — EK9 has no 'implements' keyword for interfaces. Define operators directly on the class.

Incorrect:

      implements Comparable<Product>

Correct:

      operator <=> as pure
        -> other as Product
        <- rtn as Integer: price <=> other.price
Other ways to ask this
  • How do I make a class sortable in EK9?
  • Write a class I can use in a sorted stream pipeline
  • Code a class with all comparison operators

Coming from another language?

Java: implements Comparable<T>. Python: __lt__, __gt__. Rust: derive Ord. EK9: define <=> then derive comparison operators.

Keywords: class, comparison, operator, write, code, coder, sort