Fake Operators and Equality

In Ruby, most operators are actually methods:

1 + 3
# is actually...
1.+(3)

4 == 4
# is actually...
4.==(4)

This is true for the operators bellow:

Operators Description
`[]`, `[]=` Collection element getter/setter
`**` Exponential operator
`!`, `~`, `+`, `-` Not, complement, unary plus and minus
`*`, `/`, `%` Multiply, divide, and modulo
`+`, `-` Plus, minus
`>>`, `<<` Right and left shift
`&` Bitwise "and"
`^`, `|` Bitwise exclusive and inclusive "or"
`<=`, `<`, `>`, `>=` Less than/equal to, etc
`<=>`, `==`, `===`, `!=`, `=~`, `!~` Equality and pattern matching

Operators that are, in fact, methods, can be defined in custom classes 1 to change their default behaviors. For example we could compare two Person classes by their age. To do that, we could use the greater than operator (>) between two instances:

class Person
  def initialize(age)
    @age = age
  end

  def >(other_person)
    age > other_person.age
  end

  def ==(other_person)
    age == other_person.age
  end

  protected

  attr_reader :age
end

arthur = Person.new(44)
tommy  = Person.new(43)

arthur > tommy  # => true
arthur == tommy # => false

(Note the use of protected which is perfect for this use case.)

Now, defining == method gives us !=. This is not true for > though.

arthur != tommy # => true
arthur < tommy  # => NoMethodError (undefined method `<' for...

If we know we are going to use a lot of comparison, we can include the Comparable module to our class and define <=>. By doing this, we are effectively defining all comparison methods.

class Person
  include Comparable

  def initialize(age)
    @age = age
  end

  def <=>(other_person)
    age <=> other_person.age
  end

  protected

  attr_reader :age
end

arthur = Person.new(44)
tommy  = Person.new(43)

arthur > tommy  # => true
arthur < tommy  # => false
arthur == tommy # => false

For the sake of completeness, let’s add that there are also operators which are not methods (and thus, can’t be defined):

Operators Description
`.`, `::` Method/constant resolution operators
`&&` Logical "and"
`||` Logical "or"
`..`, `...` Inclusive range, exclusive range
`?` `:` Ternary if-then-else
`=`, `%=`, `/=`, `-=`, `+=`, `|=`, `&=`, `>>=`, `<<=`, `*=`, `&&=`, `||=`, `**=`, `{` Assignment/shortcuts, block delimiter
Footnotes
1.
They can also be re-defined for default class. This is called Monkey Patching and is very dangerous, and thus, should be avoided for the time being.