In any programming language understanding scopes is very important. Scope defines visibility for variables, methods, classes, objects, constants. I’m going to discuss how ruby defines scopes for methods. Most of the OO programming languages have three scopes for methods public, private and protected. Ruby also has public, private and protected scopes. I’m not going into the details of each scope. I’ll be discussing about how scope is defined for a method in ruby.
Let’s take a look at the above code, looks simple enough to understand right. Good, now let’s see the following code.
Some of you must have left wondering What changed? Why private_method is accessible for Foo class? Looking at the code, for those whom ruby is not first OO programming language above behavior of ruby must be weird.
Most of the ruby developers comes from different OO programming language background, so they tend to ignore most of details about ruby language. We will see closely at ruby source code to understand how ruby defines scopes for methods. Let's start with what is
private in ruby, is it a method or keyword or something else?
private is a method defined on Module class which is super class of class Class. When you write private inside body of class(Most of know body of class is a executable code in ruby) ruby calls
rb_mod_private method. Which internally calls following two methods if you call private without any parameters then
vm_cref_set_visibility is called to set the visibility of
rb_vm_cref(we'll discuss in detail). otherwise
METHOD_ENTRY_VISI_SET this macro will be called to set the visibility of the method.
Let's follow the code for
vm_cref_set_visibility function sets the scope visibility for
rb_vm_cref() returns reference to the current object from the current control frame(we will discuss in detail about this in next blogpost).
Now we will see how ruby defines a method and sets the scope of the method.
When you define method in ruby with
vm_define_method is called. If you look at the signature of this method.
vm_define_method accepts a flag called
is_singleton which decides whether to add method on signleton class of a class(often called eigenclass or virtual class) or add instance level methods.
When you define method in following way.
is_singleton = false, which means define instance level method. Now in that case visibility of the method is retrieved from
rb_scope_visibility_get function which retrieves visibility from
rb_vm_cref() which is a reference to the current object in current control frame as we discussed earlier.
But in case of of following code.
is_singleton = true, which means add method on signleton class of a class(often called eigenclass or virtual class). Now in that case visibility of the method is set to
Now I hope you understand it better how ruby defines visibility for methods. Let's understand if you want to define visibility for eigenclass methods.
In above example of code, ruby will set scope in context of eigenclass which will be used to set visibility on methods defined for eigenclass.