Ruby gives three types of method visibility:
- Public methods can be called by everyone - no access control is enforced. A class's instance methods (these do not belong only to one object; instead, every instance of the class can call them) are public by default; anyone can call them. The initialize method is always private.
- Protected methods can be invoked only by objects of the defining class and its subclasses. Access is kept within the family. However, usage of protected is limited.
- Private methods cannot be called with an explicit receiver - the receiver is always self. This means that private methods can be called only in the context of the current object; you cannot invoke another object's private methods.
In Ruby, things are a bit different. Both private and protected methods can be called by any instance
of the defining class and its subclasses. Inheritance plays absolutely
no role in determining the visibility of a method. The difference
instead is that private methods can never be called with an explicit
receiver, even if the receiver is
Consider the following example:
In summary, method visibility and access control can be a bit confusing at first, especially if you’re coming over to Ruby from some other OO language. If you’re still confused, there’s more information available here and here. Do yourself a favor and make sure you understand, cuz it’s important stuff!
self
. This means that
it’s not possible to access another object’s private methods, even if
the object is of the same type as the caller. A private method must be called from within the calling object.Consider the following example:
The public method can of course be accessed from anywhere (in this case, outside the class with an explicit receiver) and both private and protected methods ofclass Person def public_method "public" end
protected def protected_method "protected" end
private def private_method "private" end end
class SalesPerson < Person def check_protected_method_explicit_receiver "#{self.protected_method} method OK with explicit receiver" rescue "failure accessing protected method with explicit receiver" end
def check_protected_method_implicit_receiver "#{protected_method} method OK with implicit receiver" rescue "failure accessing protected method with implicit receiver" end
def check_private_method_explicit_receiver "#{self.private_method} method OK with explicit receiver" rescue "failure accessing private method with explicit receiver" end
def check_private_method_implicit_receiver "#{private_method} method OK with implicit receiver" rescue "failure accessing private method with implicit receiver" end end
Person
will obviously raise a NoMethodError
.Person.new.public_method
=> "public"
Person.new.private_method
=> NoMethodError: private method `private_method' called for #
Person.new.protected_method
=> NoMethodError: protected method `protected_method' called for #
So the protected method cannot be accessed outside of the class or
it’s subclass, but from within the subclass, using it with either an
implicit or explicit receiver works fine:SalesPerson.new.check_protected_method_explicit_receiver
=> "protected method OK with explicit receiver"
SalesPerson.new.check_protected_method_implicit_receiver
=> "protected method OK with implicit receiver"
The private method can also be called from the subclass, but note how it only works with an implicit receiver:SalesPerson.new.check_private_method_explicit_receiver
=> "failure accessing private method with explicit receiver"
SalesPerson.new.check_private_method_implicit_receiver
=> "private method OK with implicit receiver"
This also means you can do stuff like:We’re accessing theclass Person def ==(other) protected_method == other.protected_method end end
x = SalesPerson.new y = Person.new x == y => true
protected_method
of another class instance that shares our type here, specifying an explicit receiver. If you were to try to use private_method
instead, a NoMethodError
would be raised. You could also just call other.send("private_method")
.In summary, method visibility and access control can be a bit confusing at first, especially if you’re coming over to Ruby from some other OO language. If you’re still confused, there’s more information available here and here. Do yourself a favor and make sure you understand, cuz it’s important stuff!
No comments:
Post a Comment