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" endprotected def protected_method "protected" endprivate def private_method "private" end endclass SalesPerson < Person def check_protected_method_explicit_receiver "#{self.protected_method} method OK with explicit receiver" rescue "failure accessing protected method with explicit receiver" enddef check_protected_method_implicit_receiver "#{protected_method} method OK with implicit receiver" rescue "failure accessing protected method with implicit receiver" enddef check_private_method_explicit_receiver "#{self.private_method} method OK with explicit receiver" rescue "failure accessing private method with explicit receiver" enddef 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 endx = 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