Access control in Ruby

I will try and take a different approach for understanding the ruby access controls in a much more simpler way.

Ruby provides you with 3 different ways to handle the visibility of the methods i.e public, protected and private. I think everyone agrees 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 way which catches your 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 difference lies in how ruby handles the protected and public methods and how something like c++ handles it.

There are 2 ways I can go about this, first I explain you all the theoretical details and then show you some code, or second, I show you the code first and then touch upon the details of it. To understand this in a better way, I am going to go with the latter approach.

SCENARIO 1

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.

Lets look at the 2nd scenario.
SCENARIO 2


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. 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. I 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

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

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.

Advertisements