Build Ranges out of custom class instances
The objects of the class Range
implement sequential intervals of values.
Ever wondered how to build ranges out of custom class objects?
Yes, this is possible and it can be achieved by following a few simple steps.
Ranges of custom objects example
Let's imagine that we need to have the ability to create ranges of this sort (Identifier.new(3)..Identifier.new(10))
.
Our class Identifier
creates strings like this one: "65-A"
where the integers at the start are the ASCII index for the character shown at the end of the string.
The three steps are to:
- include the
Comparable
module - define the
<=>
operator. - define the method
succ
Here is a brief description of what happens here:
The Comparable
module
The module Comparable
adds the instance methods: <
, >
, <=
, >=
, ==
, between?
, clamp
.
The three-way comparison operator
The <=>
three-way comparison operator, (a.k.a. the spaceship operator) gives us the ability to compare two instances of the same class in the sense of <
, >
, <=
, >=
, ==
operators.
The expression a <=> b
will output either -1
, 0
, or 1
depending which of the elements has a lesser value, compared to the other.
The method Comparable#clamp
relies on the <=>
operator.
The succ
method
The succ
method evaluates the "next" instance from the sequence. Think of it as an increment operator.
For example: 1.succ
, will evaluate to 2
in the context of integers.
There are some data types such as Float
, where there is no way to determine the "next" element due to the nature of the elements.
Example
Now we can do fancy stuff, for example:
This is what happens when we invoke to_s
on every instance from the (Identifier.new(65)..Identifier.new(90))
range:
Conclusion
Mixing the Comparable
module and defining the succ
and <=>
gives us the ability to create ranges out of custom class instances.