5

The Many Faces of Ruby's Top-level

 3 years ago
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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK