Lets take a different approach to understand the ruby access controls in a much simpler way. Ruby provides us with 3 different ways to handle the visibility of the methods i.e public, protected and private.
We all agree that we can access a public method from anywhere inside the class it is declared in or from outside the class.
It is the protected and private methods that catch our attention. We all have heard or read that ruby is different from all the other object oriented programming languages. But in what context? One of the differences lies in how ruby handles the protected and public methods and how other languages like c++ handle them.
There are 2 ways we can go about this – first I can explain all the theoretical details and then show some code or we can see code first and then touch upon the details. Lets take the latter approach.
SCENARIO 1 – public methods.
class A def public_method p "public method in A" protected_method private_method end protected def protected_method p "protected method in A" end private def private_method p "private method in A" end end a = A.new a.public_method
The output looks like this
"public method in A" "protected method in A" "private method in A"
In above code snippet, there is a class A which has a public, protected and private method. As seen in the output, the protected and private methods are also accessible in the class A just like the public method. Nothing unusual here, lets look at the 2nd scenario.
SCENARIO 2 – private methods are inherited
class A def public_method p "public method in A" end protected def protected_method p "protected method in A" end private def private_method p "private method in A" end end class B < A def public_method_in_b public_method protected_method private_method end end b = B.new b.public_method_in_b
The output for the above scenario is:
"public method in A" "protected method in A" "private method in A"
In above scenario, we have another class B which inherits from class A. Now first of all, in all OOPs languages, private methods are not inherited from the parent class. But in ruby, private methods are also inherited just like public and protected are. And this is just one little thing which ruby does differently. Now that we are all on board that private methods are also inherited, lets look at the code. We have defined a public method in class B which accesses the public, protected and private methods of class A and as seen in the output all of them are very much accessible.
Then the question arises, what is the difference between public, protected and private methods? Because all of them are inherited, all of them could be accessed from inside the class they were defined or their child classes. Lets look at the next code snippet to understand this.
SCENARIO 3 – accessing protected and private methods
class A def public_method p "public method in A" end protected def protected_method p "protected method in A" end private def private_method p "private method in A" end end class B < A def public_method_in_b public_method end end b = B.new b.public_method
This would give the output as expected “public method in A”. But when I do something like this in above code
b.protected_method rescue p "Cant access protected method outside the class" b.private_method rescue p "Cant access private method outside the class"
Then the output is:
"Cant access protected method outside the class" "Cant access private method outside the class"
So here is the difference between public, protected and private methods in ruby. We can access the public method outside the class they were defined in, but we cant access the protected and private outside the classes they were defined in.
So, then what is the difference between protected and private methods.
“In ruby, private methods are not accessible by a explicit receiver.”
To understand this statement, lets look at the next code snippet.
SCENARIO 4 – accessing protected methods with explicit receiver
class A def public_method p "public method in A" end protected def protected_method p "protected method in A" end private def private_method p "private method in A" end end class B < A def public_method_in_b public_method b1 = B.new b1.protected_method b1.private_method end end b = B.new b.public_method_in_b
The output for this last scenario is:
"public method in A" "protected method in A" (NoMethodError): private method `private_method' called for #<B:0x000000023a5bb8>
Here we try to access the protected and private method from inside the class but with an explicit receiver. As seen in the output, protected methods are accessible with an explicit receiver but private methods are not.
I hope this blog post will help you in understanding the concept of access control in ruby a little better. Your feedback and comments are appreciated.
great!!! Thank you very much
Well explained
Hi, I am new to Ruby so please excuse me if I ask the wrong questions. On your scenario 2 when you create the B class and define the public method in B is that considered modifying the public method in A or does that mean that the B class will have two public methods in it?