Access Control in Ruby – understanding public, protected and private

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.

Advertisements

About Rishi Jain

I am a ruby on rails developer at Josh Software, Pune.
This entry was posted in Ruby, Tutorials and tagged , , , . Bookmark the permalink.

2 Responses to Access Control in Ruby – understanding public, protected and private

  1. Nguyen Duy Khah says:

    great!!! Thank you very much

  2. Avinash says:

    Well explained

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s