Now a days I have started learning Ruby and/ Rails because my new job requires these languages. While programming in Ruby, it feels so natural and syntax of Ruby is much cleaner compared to other programming languages that i did in the past. However there are few confusing things in Ruby when you come from other programming languages such as Java, C#, C++ etc. One of those things are methods visibility in Ruby. In Ruby every methods are public by default.
class Foo def say_hello puts "Hello World" end def say_bye puts "Good Bye" end end
now in above code both the methods “say_hello” and “say_bye” are public by default so if i create object of Foo class and call methods “say_hello” and “say_bye” it will work as expected
foo = Foo.new foo.say_hello # will print "Hello Wolrd" foo.say_bye # will print "Good bye"
Now lets make method “say_bye” to private, in Ruby to make any method private we write keyword private and then define methods underneath the word private. Any method written after word “private” will all be private
class Foo def say_hello puts "Hello World" end private def say_bye puts "Good Bye" end end
foo = Foo.new foo.say_hello # will print "Hello Wolrd" foo.say_bye # Error: calling private method
So far everything is working as expected. We know that we can’t call method “say_bye” directly on foo object because “say_bye” is private method but we can call method “say_bye” inside “say_hello” method. So far nothing new. Now lets create another class called “Bar” which will inheritance from “Foo” class
class Bar < Foo def say_bar puts "I am bar." end end
bar = Bar.new bar.say_bar # will print "I am bar."
Now from langauges like Java, we know that during inheritance, child class will inherit public and protect methods from parent class. But in Ruby it’s different, in Ruby child class also inherit private methods as well. To demonstrate this concept lets call private method “say_bye” of “Foo” class inside “Bar” class
class Bar < Foo def say_bar puts "I am bar." say_bye end end
bar = Bar.new bar.say_bar # will print "I am bar." # Good Bye"
If we see the result we print out “I am bar” and “Good Bye”.This shows that in Ruby child class inherite private method from parent class. You can call those private methods inside your class but you can not call them on object. Code show below will not work because you are trying to invoke private method directly on the object.
bar = Bar.new bar.say_bye # Error
Another surprising feature of Ruby which i haven’t seen in languages like Java is, even you make your methods private, you can still force it and call it as public. Ruby understands that’s its programmers responsibility to know what they are doing. It allows method to be private but if programmers still want to invoke private methods then Ruby won’t stop programmers from doing so. We can invoke private methods by using “:send”.
foo = Foo.new foo.say_hello # will print "Hello Wolrd" foo.send(:say_bye) # will print "Good Bye" bar = Bar.new bar.say_bar # will print "I am bar." bar.send(:say_bye) # will print "Good Bye"