Ruby – Visibility of private and protected module methods when mixed into a class
Consider you have a module defining a public, a protected and a private method. What happens to this visibility declaration after mixing the module into a class?
Does Ruby ignore visibility information or does Ruby take over the visiblity settings?
The following example demonstrates that Ruby preserves the module’s visibility settings and keeps private methods private and protected methods protected:
module MyMethods def my_public_method puts "Public" end protected def my_protected_method puts "Protected" end private def my_private_method puts "Private" end end
require 'my_methods' class MyClass include MyMethods def invoke_my_protected_method my_protected_method end def invoke_my_private_method my_private_method end end class MyInheritedClass < MyClass def invoke_my_protected_method_from_subclass my_protected_method end def invoke_my_private_method_from_subclass my_private_method end end mc = MyClass.new mc.my_public_method begin mc.my_protected_method rescue NoMethodError puts "Unable to call a protected method." end begin mc.my_private_method rescue NoMethodError puts "Unable to call a private method." end mc.invoke_my_protected_method mc.invoke_my_private_method mic = MyInheritedClass.new mic.invoke_my_protected_method_from_subclass begin mic.invoke_my_private_method rescue NoMethodError puts "Unable to call a private method of the parent class." end
Output looks like this:
Public Unable to call a protected method. Unable to call a private method. Protected Private Protected Private
What we see is pretty much the same as declaring the module methods directly in our class. The fact that we use a mix-in didn’t change anything at all.
- Our protected method may be invoked in MyClass as well as in MyInheritedClass but not outside of our classes.
- The private method can only be used within MyClass but outside or in the inherited class MyInheritedClass.
So everything is just as expected. Isn’t Ruby a great thing?