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
For example, we might have the following method in our
To signify that the 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
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
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>
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:
Post a Comment