DEV Community

Cover image for The protected modifier in Ruby
Rafał Piekara
Rafał Piekara

Posted on

The protected modifier in Ruby

Recruitment interviews, especially their technical part, usually follow a specific pattern. It is easy to anticipate the questions that may be asked. It is often the case that the developer who asks them is taken out of the project and busy with solving problems on a daily basis and does not have time to prepare some original and surprising questions (unless he is a sadist and likes to bully candidates, but who of us did not recruit and did not have a killer question up his sleeve?), so google for example "Ruby interview questions". The second possibility is that this developer is already on the nth interview, always asking the same questions out of pure routine. He may also ask what he himself was asked about when he was the candidate. I want to present to you and explain an issue that will appear in 90% of a job interview for a Ruby on Rails developer, and it is about the Protected modifier in Ruby.

What's the difference between Public, Private, and Protected, which are access modifiers?

Sounds familiar?

You may encounter these words in other languages. To understand their slightly different meaning in Ruby, let's take a look at how they function in Java, C # and PHP for comparison.

Java

Public - access to a method in a given package and in any other package

Private - access only within classes and not inheritable

Protected - This is almost identical to private, with one subtle difference, protected methods can be inherited

"C#"

Public - access to the method is unlimited from anywhere in the application

Private - methods available only within the class or structure in which they are defined

Protected - the method is available in the child class only if accessed through the child class

PHP

Public - the method is visible from the inside of the class, derived classes and outside the class

Private - methods available only from inside the class

Protected - the method is visible in all classes that inherit from the base class, including the base class

RUBY 💖💋💪

First, to be perfectly clear, these three words: public, private, protected, commonly referred to as access modifiers, are not really keywords, but ... methods.

Remember that in Ruby, the code which does something is called method, and is defined by the words def and end at the beginning and end of a given batch of code.

Public in Ruby

It is no different from any other language. In Ruby, all methods not explicitly specified by the other two modifiers are public, except for the class constructor, the initialize method, which is always private.

Public methods can be invoked by anyone, anywhere, and are therefore not subject to any restrictions. For the method to be public, no keyword is required, it is enough to declare it above the private and protected declarations.

Interesting fact!

Globally declared public methods outside of all classes are actually private methods of an instance of Object, Ruby's super extra mother class.

Private in Ruby

The recipient of a private method is always self.

They cannot be called for any instance of the class in which they are defined, because they operate only inside that class, which means that they can only be called in the context of a given object.

They can only be called in other instance methods of the same class and its subclasses. Private methods in Ruby are inherited.

When using private methods in the body of other methods, remember that we always do it in a function style, that is:

private_method ()

not

instance.private_method ()

or

self.private_method ()

It also follows that the private methods of another object cannot be accessed, even if that object is of the same class.

Protected in Ruby

Access to protected methods is restricted to the family only, but, compared to other languages, they can be invoked by objects of the same class but inside those objects.

They can always be called on behalf of any instance of a class or a subclass of it, so unlike private, they are not limited to only implicit calls on behalf of self.

Protected is used to operate on the internal state of other objects of the same class.

It is an access method that allows an instance of a given class to share the internal state, but at the same time prevents consumers of that class from accessing this state from the outside.

To quote Matz, the creator of Ruby:

,,A protected method defined in class C can be called on behalf of an O object by a method in P if classes O and P are subclasses of class C or are equal to it.”

Here are some examples to better understand the Protected modifier in Ruby.

We have the Employee class and two employees who symbolize its instances. Suppose a scenario where the boss wants to compare their salaries without exposing them to the outside world.

class Employee
  attr_reader :salary
  protected :salary

  def greater_salary_than(other_employee)
    @salary > other_employee.salary
  end
end

first_employee = Employee.new
second_employee = Employee.new
first_employee.grater_salary_than(second_employee)

class Person
  def older_than?(other_person)
    age > other_person.age
  end

  protected
  def age@age
  end
end
Enter fullscreen mode Exit fullscreen mode

You can clearly see what I wrote about above. A protected method is not available outside the context of a given object, but is available inside the context of another object, if and only if the object is of the same type.

The_protected_modifier

Additional information about Protected in Ruby and other modifiers

  • protected method can be called in the context of the given object as method () or self.method ()
  • Access modifiers can be declared in two ways:
  • all methods after the word private will be private unless we use protected somewhere along the way. Similarly, all methods after this declaration will be protected, unless we use the private modifier somewhere along the way
  • the second way is to first declare all the methods and then establish their access by listing their names in conjunction with the appropriate access modifier
# I way
private
def method

protected
def method 

# II way
def method
end

protected :method
Enter fullscreen mode Exit fullscreen mode
  • calling respond_to? for a protected method it will return false. For clarification, respond_to? is a method that returns true if the object implements the method given as an argument. By default, it does not include private methods. They can be considered by passing the second argument to this method as true
  • let's go back to private methods for a moment. Although I wrote that we do not have access to them, there is one exception here. A trick known only to those who don't speak Rabi. Namely, you can get to them by calling the private method with the send method or by evaluating the block in the context of the object using the instance_eval method
p = Page.new
p.send :some_private_method
p.instance_eval(some_private_method)

Enter fullscreen mode Exit fullscreen mode

This is a topic for another lecture, treat it as a Swiss curiosity, don't try it at home.

BTW, there is also a public_send method which works like send, except that private methods are omitted. It's easy to get confused.

Top comments (0)