Friday 17 July 2015

Private and Protected Method In Ruby

Public, Protected and Private refer to the accessibility of those methods.

By default, all methods are Public. If you do not specify the accessibility of a method, it will be Public.
Protected and Private methods are not publicly accessible and so when you have an instance of an Object you will not be able to call those methods.

Protected and Private methods also have differences around how you can use them within the context of an Object.


Private Methods


Both Private and Protected methods are not accessible from outside of the object as they are used internally to the object.
Another important aspect of good object-oriented design is that the consumer of an object should not have to know how that object is implemented.
Private methods and Protected methods, whilst both being inaccessible outside of the scope of the object, have a subtle difference.
I think it’s easier to understand Private methods, and so we’ll start here.
To define a private method you use the private keyword. private is not actually a keyword, it’s a method, but for all intents and purposes, it’s easier to just think of it as a keyword.
For example, we might have the following method in our Product class:


class Product
attr_accessor :name, :quantity

def initialize(name)
  @name = name
  @quantity = 1
end

def increment
  @quantity += 1
end

private
  def stock_count
    100
  end
end


To signify that the stock_count method is private we can place it under the private heading.
There is actually a couple of different ways to define private methods, but I think the method above is the most common.
Now when we have an instance of the Product object, we can’t call the stock_count method because it is private:



milk = Product.new("Milk")
=> #

milk.stock_count
NoMethodError: private method 'stock_count' called for #




In order to call the stock_count method, you need to be within the scope of the object:

class Product
attr_accessor :name, :quantity

def initialize(name)
  @name = name
  @quantity = 1

puts "There are #{stock_count} in stock"
end

def increment
  @quantity += 1
end

private
  def stock_count
    100
  end
end


Now when we instantiate a new instance of the object, we will see the stock count:

milk = Product.new("Milk")
  There are 100 in stock
=> #



So the only way to call a Private method is to do so within the context of the object instance.
However, an interesting thing to note about Private Ruby methods is the fact that a Private method cannot be called with an explicit receiver, even if that receiver is itself.
When I say “receiver”, I mean the object that the method is being called from.
So for example:


class Product
  attr_accessor :name, :quantity

def initialize(name)
  @name = name
  @quantity = 1

puts "There are #{self.stock_count} in stock"
end

private
  def stock_count
    100
  end
end


In this example I’ve modified the initialize method to use self.stock_count. In this case, self refers to the current object.
However, when you attempt to create a new instance of Product you will get an error:

milk = Product.new("milk")
NoMethodError: private method `stock_count’ called for #


So you can only call Private methods from the current context of the object, and you can’t call Private methods with a receiver, even if that receiver is self.

 Protected Methods 

Finally we have Protected methods. A Protected method is not accessible from outside of the context of the object, but it is accessible from inside the context of another object of the same type.
For example, imagine we have the following sku method on the Product class:

class Product
attr_accessor :name, :quantity

def initialize(name)
  @name = name
  @quantity = 1

puts "The SKU is #{sku}"
end

protected
  def sku
   name.crypt("yo")
  end
end


In this example we are generating a SKU from the product’s name.
As with the Private method example from earlier, this method is not accessible outside the context of the object:

milk = Product.new("Milk")
The SKU is yo.B6xygWtQ1w
=> #<Product:0x007fd7a2184058 @name="Milk", @quantity=1>
milk.sku
NoMethodError: protected method 'sku' called for #<Product:0x007fd7a2184058 @name="Milk", @quantity=1>
However, if you call the method with self it will work:

class Product
attr_accessor :name, :quantity

def initialize(name)
  @name = name
  @quantity = 1

puts "The SKU is #{self.sku}"
end

protected
  def sku
   name.crypt("yo")
  end
end


So a Protected class method can be called within the context of an object of the same type.
This means you can call Protected class methods of other objects inside an object of the same type. For example:


class Product
attr_accessor :name, :quantity

def initialize(name)
@name = name
@quantity = 1
end

def ==(other)
  self.sku == other.sku
 end

protected
  def sku
    name.crypt("yo")
  end
end

In this class we’ve implement the == method to assert equality between two objects. This method accepts another Product object and will call the Protected sku method.
If the two Product objects have the same name, they will be considered equal:


milk1 = Product.new("Milk")
=> #

milk2 = Product.new("Milk")
=> #

bread = Product.new("Bread")
=> #

milk1 == bread
=> false

milk1 == milk2
yo
=> true


So the important thing to note here is, you can call Protected methods inside the context of an object of the same type.

Conclusion  

The differences between Public, Private and Protected methods can seem confusing at first, particularly the differences between Private and Protected methods.
Writing a clean and easy to use public interface for your objects is a very important part of the design process. The public API will say a lot about the object and how it should be used. It’s important to take care and ensure you make good choices when deciding on method names and what methods should be public.

The choice between Private and Protected will come down to how you intend your object to be used.
As with just about everything else in programming, learning via experience is really the only way to progress. If today’s tutorial seemed like a lot to take in, don’t worry about it. As long as you keep exploring, you will eventually find the way.

:::Happy hacker ;) 

No comments:

Salesforce CRM vs. Zoho: A Comparative Analysis

Introduction: Selecting the right customer relationship management (CRM) software is crucial for businesses seeking to streamline their sal...