08.10.2016
Operator Overload
Operator Overload, I have been overloading operators with objects before I was introduced to the term itself. In fact, operator overload is pretty common in the world of programming languages. We just take things for granted. In fact, we take things for granted all the time anyways.
Let’s define what is operator overload. According to Techopedia, Operator overloading is a technique by which operators used in a programming language are implemented in user-defined types with customized logic that is based on the types of arguments passed.
What does that mean?
Well, I don’t quite understand completely either, but let’s do some live coding, shall we?
Let’s take a look at the String class in Ruby. When you define, or create two strings, you can do math on it. Simple add them together and you can easily concatenate the two strings. This allows you to effortlessly join the two together:
[1] pry(main)> string1 = "Hello" => "Hello" [2] pry(main)> string2 = "World" => "World" [3] pry(main)> string1 + " " + string2 => "Hello World"
If addition works in string, let’s play with subtraction too!
[1] pry(main)> string1 = "Hello World" => "Hello World" [2] pry(main)> string2 = "World" => "World" [3] pry(main)> string1 - string2 NoMethodError: undefined method `-' for "Hello World":String
Oh no, NoMethodError! I wonder why . .
It is because in the String library, the creator did not include the - (subtraction) operator. Therefore, the computer does not know the logic behind it, or the meaning behind that particular operator. Though it may seems very logical to the human brain, it is not to the computer. The user or the creator has to manually define all operator operations for each and every object. The best way to understand it is to treat the operator as the name of the method. Let’s take a look at the code below:
[1] pry(main)> class String [1] pry(main)* def subtract(string) [1] pry(main)* self.gsub(string,"") [1] pry(main)* end [1] pry(main)* end => :subtract [2] pry(main)> string1 = "Helloooooo" => "Helloooooo" [3] pry(main)> string2 = "ooooo" => "ooooo" [4] pry(main)> string1.subtract(string2) => "Hello"
This seems so boring. Let’s make things look more interesting with the help of operator overload.
[1] pry(main)> class String [1] pry(main)* def -(string) [1] pry(main)* self.gsub(string,"") [1] pry(main)* end [1] pry(main)* end => :- [2] pry(main)> string1 = "Hell no" => "Hell no" [3] pry(main)> string2 = " n" => " n" [4] pry(main)> string1 - string2 => "Hello"
How cool is that?
You may also override the existing methods as well. Which means…. You can use this technique to mess with your friends !
[1] pry(main)> class Fixnum [1] pry(main)* def * (num) [1] pry(main)* self - num [1] pry(main)* end [1] pry(main)* end => :* [2] pry(main)> 10 * 5 => 5
Messing with your friends is not the main purpose of this blog. The important thing is to get the practicality of operator overload into practice. Here is a little demo with doing subtraction and addition with an object called Circle using its area.
class Circle @@pi = Math::PI attr_reader :area, :radius def initialize( area: nil , radius: nil) if area && area > 0 @area = area @radius = (Math.sqrt(area/@@pi)) elsif radius && radius > 0 @radius = radius @area = @@pi * (radius**2) else @area = @@pi @radius = 1 end end # Operator Overload here: def +(circle) Circle.new(area: (area+circle.area)) end def -(circle) Circle.new(area: (area-circle.area)) end def *(circle) Circle.new(area: (area*circle.area)) end # having too much fun here, playing with meaningless circle definitions def %(circle) Circle.new(area: (area%circle.area)) end def /(circle) Circle.new(area: (area/circle.area)) end def **(circle) Circle.new(area: (area**circle.area)) end #this method overrides the puts statement def to_s puts "Area:\t#{@area}" puts "Radius:\t#{@radius}" end end a = Circle.new(radius: 2) b = Circle.new puts a * b #output Area: 39.47841760435743 Radius: 3.5449077018110318
Ta da!
I hope you have enjoyed it and have a nice day,
-irevived