Can a trait define comparison and hashcode operators in EK9?
← Operators and Expressions · Ref: Q1051
Yes, traits can define operator signatures that implementing classes must provide. A trait can declare abstract operators or provide default implementations.
Abstract operator in a trait (no body):
defines trait Rankable operator <=> as pure -> other as Rankable <- rtn as Integer?
Default operator in a trait (with body):
defines trait Identifiable operator #? as pure <- rtn as Integer: 0
Any class 'with trait of Rankable' must implement <=>. The trait contract guarantees that all Rankable objects can be compared.
This pattern is useful for:
- Defining sortable contracts
- Ensuring all types in a collection support comparison
- Building generic algorithms that depend on ordering
Note: override is required when implementing trait operators in a class.
See Q1049 for comparison operators on records. See Q1050 for coalescing on classes. See Q210 for trait delegation.
Example
defines module qa.operators.operatorsontrait defines trait Rankable rank() as pure <- rtn as Integer? defines class Task with trait of Rankable priority as Integer: 0 taskName as String: String() Task() -> taskName as String priority as Integer this.taskName :=: taskName this.priority :=: priority override rank() as pure <- rtn as Integer: priority operator <=> as pure -> other as Task <- rtn as Integer: priority <=> other.priority operator < as pure -> other as Task <- rtn as Boolean: (this <=> other) < 0 operator > as pure -> other as Task <- rtn as Boolean: (this <=> other) > 0 operator #? as pure <- rtn as Integer: #? priority override operator ? as pure <- rtn as Boolean: taskName? and priority? operator $ as pure <- rtn as String: `${taskName}(${priority})` defines program TraitOperatorsDemo() stdout <- Stdout() taskA <- Task("Fix bug", 3) taskB <- Task("Deploy", 8) stdout.println(`A < B: ${taskA < taskB}`) stdout.println(`A > B: ${taskA > taskB}`) stdout.println(`A hash: ${#? taskA}`) //Coalescing: get higher priority urgent <- taskA >? taskB stdout.println(`More urgent: ${urgent}`)
Common mistakes
E05120 — Overriding an inherited trait member (here rank() from trait Rankable) requires the 'override' keyword, otherwise the compiler reports E05120. See ek9 -h E05120 for details.
Incorrect:
rank() as pure
Correct:
override rank() as pure
Other ways to ask this
- Show me operator definitions inside a trait
- Do traits support #? and comparison operators?
- Define a sortable contract using a trait with operators
Coming from another language?
Java: Comparable interface. Rust: Ord trait. Python: __lt__ protocol. EK9: trait with operator signatures.
Keywords: hashcode, trait, comparison, operator, abstract, contract