breaking into the unknown…

difference between private protected public in ruby

private, protected and public control the visibility of methods in ruby class .By default methods in ruby are public except global and initialize method which are private by default. As far as variable are concerned they are private by default as variable can’t be seen by them self but through getter and setter method defined for a variable. you can define the getter and setter method yourself, which is not actually needed as it can be achieved by using :attr_accessor. the variables for which you have defined getter and setter methods behave as public. constants are effectively public , there is no way to define a constant that is inaccessible to outside use. we can say that public, private and protected apply only to methods

private, protected and public are not any keyword but actual method of object class that operate on any other class, dynamically altering the visibility of its methods . you can get the list of private, protected or public method of a class by using private_methods , protected_methods and public_methods on it.

private, protected and public take methods name as argument. If you do not pass argument all the method following them will have the same visibility until it is changed by applying the other. Let us illustrate it with examples in visibility_demo.rb files

# this global method defined outside class so private
def iam_global
puts "Iam global"
endclass VisibilityDemo
def initialize
@message = "Iam the class demonstrating visibility in ruby"
end # No visibility specifier given so public by defaultdef pub_method
puts "Iam public"
end
private
# This method appears after the private' visibility specifier so privatedef pri_method
puts "Iam private"
end # This method is also private because the previous visibility not overridden
# specifier has not been overriddendef pri_method2
puts "Iam private"
end
protected
# This method appears after the protected visibility specifier so protecteddef pro_method
puts "Iam protected"
end
public
#this method overridden above protected specifier and become publicdef pub_method2
puts "Iam public"
end
end

The risk in above way of defining the visibility (visibility specifier without arguments) is that all following method will have same behaviour(try by changing the position of say private, keep it at top), which we not always want, so it is better to use them in argument form if the list of particular visibility is not very long. Let us redefine it in argument form and also add some other piece of code, needed to demo visibility behaviour.

O.K, so we now know how to set the visibility of a method. Let us now see how the visibility specifier change the behaviour of methods in its own class and its inherited classes.

NOTE : before you proceed you must be clear onself and implicit and explicit receiverof a method . You should also know that, there is three way of calling any method : method_name , self.method_name, @object.method_name

1 => irrespective of its visibility any method can be called only in its class hierarchy

NOTE :Here there is one exception for protected method, protected method can also be called on a object if its belongs to the same class as self.

In the above output , you are running the code from irb and so at this point of program self is main, but the object @visbility_demo belongs to VisibilityDemo class, since the class of self and the class of object is different, the protected method throw error. See the below output where protected method called on explicit object and worked fine.

> @visbiility_demo = VisibilityDemo.new # creating object of VisibilityDemo => #<VisibilityDemo:0x955e034 @message=”Iam the class demonstrating visibility in ruby”> > obj = VisibilityDemo.new # creating another object of VisibilityDemo => #<VisibilityDemo:0x9531408 @message=”Iam the class demonstrating visibility in ruby”> > @visbiility_demo.demo_explicit_object_calling_proc(obj) #for demo_explicit_object_calling_proc method self is VisibilityDemo and since object passed to it is also of same class, the protected method worked this timeIam protected

3 => Public and Protected both can be called with self as explicit receiver but Private can’t

5 => If a private method overridden in its subclass, the method exhibit visibility as defined in subclass

see the below output in irb console

> @visibility_demo = VisibilityDemo.new # create object of VisibilityDemo class => #<VisibilityDemo:0x9e49734 @message=”Iam the class demonstrating visibility in ruby”> > @visibility_demo.pri_method2 # call the private methodNoMethodError: private method `pri_method2′ called for #<VisibilityDemo:0x9e49734> # error as expected> @inherit_visibility = InheritVisibility.new # create object of subclass of VisibilityDemo class which override the method => #<InheritVisibility:0x9f01e4c @message=”Iam the class demonstrating visibility in ruby”> > @inherit_visibility.pri_method2 # call the private method of parent againI have overrided parent and become public # it worked this time as it is overridden in the subclass

So, from the above points we can summarized the behaviour as below :

Private method can be called only implicitly (i,e without any receiver) . Protected method can be called with a explicit receiver but that should be self or if a object, the object must belong to same class as self . Public method can be called in any way in its class hierarchy .

So through above point ruby ensure that private method should never we called on a object and let ruby invoke it by its own. Remember that you can create instance of any class anywhere and if a highly secure method say which manipulate user balance, call it current_account_balance is not private, then any person can misuse it by creating the object of class and calling the method.

Here, ruby differ in private implementation in C and c++ . In C ++ “private” means “private to this class”, while in Ruby it means “private to this instance”. What this means, in C++ from code in class A, you can access any private method for any other object of type A. In Ruby, you can not: you can only access private methods for your instance of object, and not for any other object instance (of class A).

It should be also noted that, ruby prevent accidental misuse of private method, but not prevent it strictly. So if you want, you can invoke a private method on an object also with send, see the below output on console

Since, private method can’t be called on its own object also, but there are some cases where we me need it, so there we can make the method protected. Let us take a simple example below in file say my_bank.rb

So, we have a BankRate class dealing with bank rate. We want that, the current_rate should not be misused so we have made it private. This class also have a method which compare the rate of the bank with another bank . Try to load the my_bank.rb file on console

So you can see that, although the @sbi and @icici bot are object of the same class, still they can’t invoke the private method. Now change the visibility of current_method to protected in above file i,e protected :current_rate and run it again.

> load “/home/arun/Desktop/visibility_demo.rb” #load my_bank.rb file again icici have higher rate then sbi # it worked this time

So, this worked this time. This demonstrate when to use private and when to use protected.

Share this:

Like this:

Related

over 5 years experience in web development with Ruby on Rails.Involved in all stage of development lifecycle : requirement gathering, planing, coding, deployment & Knowledge transfer.
I can adept to any situation, mixup very easily with people & can be a great friend.