![](/style/images/good.png)
![](/style/images/bad.png)
The Many Faces of Ruby's Top-level
source link: https://blog.kiprosh.com/the-many-faces-of-the-top-level-in-ruby/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
In the previous post, we looked at how Ruby's top-level acts as a wrapper of the Object
class. And that the definitions you put in the top-level act as if they were put in the Object
class itself. But, there was one thing that I left out in that blog post, because it deserves its own attention.
Module extension
If you have a module:
module Foo
def bar
:bar
end
end
and you extend
it in the top-level:
extend Foo
you'd expect that it would extend
the Object
class because of what we saw in that previous post. But you'd be wrong!
Object.bar # => NoMethodError
Check yo-self before you wreck yo-self!
self
is a keyword that gives us access to the object upon which a particular method was called. It's usually available inside methods. And since the top-level kinda acts like a method, we can access the self
at the top-level!
self # => main
I know, crazy, right?
But since the top-level is a wrapper of the Object
class, self
should equal Object
, right?
self == Object # => false
Nope. In fact, self
is an instance of Object
:
self.class # => Object
And this is why when we extend
a module at the top-level, the entire Object
class doesn't get extend
-ed.
But what about module inclusion?
But if extend
doesn't work on the Object
class, then how come include
work on the Object
class?
self.method(:include).owner == self.singleton_class # => true
The above statement means that the include
method is overridden inside of self
's singleton class to act on Object
instead of self
.
Top-level as a Class/Object hybrid
So as you can see, the top-level sometimes acts as the Object
class, and sometimes acts as a modified instance of the Object
class. But it's not magic, it's clever thinking which helps it achieve that. But there are a couple of other things we can achieve now that we know that self
is an instance of Object
.
Singleton method definitions
Defining methods on self
:
def self.foo
:foo
end
will result in the method being added to self
's singleton:
foo # => :foo
and not be available to any other instance of any class:
Object.new.foo # => NoMethodError
as clear from the previous post.
Method access modification
The methods defined at the top-level are usually put inside the Object
class as private
methods:
def foo
:foo
end
Object.private_method_defined?(:foo) # => true
If you want to use other access modifiers, then you can do so:
public
def bar
:bar
end
Object.public_method_defined?(:bar) # => true
Note that if no access modifier is specified, then the default is private
, but only in a file. In an IRB session however, the default is public
. So if you want to mark a method as private
in an IRB session, use the private
keyword. Note that there is no protected
access modifier in the top-level though.
The way this works is very simple. The top-level self
has the methods public
, and private
as overridden methods which handle this task:
self.method(:public).owner == self.singleton_class # => true
self.method(:private).owner == self.singleton_class # => true
but no protected
method:
self.method(:protected) # => NameError
Top-level as a function
Since we already know that the top-level also behaves as a function (also clear from the fact that we can access self
in it), weirdly enough, you can define instance variables in it:
@foobar = :foobar
which can then be accessible through either singleton methods:
def self.foo
@foobar
end
foo # => :foobar
or can be accessible by methods defined on Object
:
def bar
@foobar
end
bar # => :foobar
So, to reiterate what I said in the first blog post,
Ruby is weird, and that's why we love it.
What do you think of this weirdness in Ruby? Do share your thoughts/feedback/suggestions in the comments below. We would love to hear them. Cheers!
References
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK