Ruby is an Object Oriented Programming language, so most everything is an object (i.e. an instance of some class), and we can call methods on our objects.
3.class => Integer "string".length => 6 [1,2,3].include? 1 => true
In Ruby, there are a couple dozen operators:
Some rocket science:
2 + 2 => 4
Operators and OOP?
These operators … don’t really look like methods being called on objects?
Well, turns out
2 + 2 is a shorthand version of
+ is just a method of the Integer class.
2.+(2) => 4 2.+ 2 # parens optional => 4
Not all operators are available everywhere - each class specifies which operators to support.
Integer, there are many operators, as we tend to like to operate on integers.
A quick glance via
[:!, :!=, :!~, :%, :&, :*, :**, :+, :-, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :, :^, ...]
There are fewer available for a class like
String; and this makes intuitive sense, as it isn’t clear what a
- would do for an instance of the
String.instance_methods.sort => [:!, :!=, :!~, :%, :*, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, ...]
But one common use of
+ for strings is concatenation:
"my string" + " has been concatenated" => "my string has been concatenated"
We can define operators on our own custom classes if we’d like.
class Cat attr_reader :lives_remaining def initialize @lives_remaining = 9 end def -(lives) @lives_remaining -= lives end end cat = Cat.new cat.lives_remaining => 9 cat - 3 cat.lives_remaining => 6
Why does this matter?
Since operators are just methods (usually displayed in shorthand), we can do method-y things!
One example is the safe navigation operator
Sometimes, if we’re not sure whether an object is
nil, we can chain
& before the method call, so we don’t get an
undefined method for nil:NilClass.
It’s quite common to see stuff like
Using the Safe Navigator for Operators
Let’s say we have a method that calculates the tax on a transaction.
def tax(amount) amount * 0.07 end tax 100 => 7
But perhaps in practice, we don’t know the values that will find their way into this method. Occasionally, the argument could be
Currently, our app would blow up:
amount = nil tax(amount) `undefined method `*' for nil:NilClass (NoMethodError)`
Let’s redefine our method using the safe navigation operator:
def tax(amount) amount&.* 0.07 end tax(nil) => nil
Another possible solution would be to protect areas of code with guard clauses (ie
return if amount.nil?), but the save navigation operator is nice and tidy, and in some circumstances, might be enough.