Removing methods from a module
How do we remove a method from one of Ruby's built-in modules (Kernel, etc)? It should be easy and obvious, right? The following snippet should be enough, right?
#remove system from module Kernel
Kernel.send :remove_method, :system
Well, not quite. While that prevents you from calling system() in the context of the current object, you can still invoke it like this:
Kernel::system('date')
What's going on?
It turns out that they way Kernel (and other built-in modules) are defined is analogous to doing the following:
module Kernel
def system (...)
...
end
module_function :system
end
Thus, system() is a method that will be added to instances of classes that include the given module (in our case, instances of any object, since Kernel is included by Object), but it is also a method in Kernel's singleton class (bear with me for a moment), or a module_method as the PickAxe book calls them. In Java parlance, they are simply static methods.
Looking at Ruby's source code, we can see that all of Kernel's methods are defined by way of the rb_define_module_function function, whose definition is:
void
rb_define_module_function(module, name, func, argc)
VALUE module;
const char *name;
VALUE (*func)();
int argc;
{
rb_define_private_method(module, name, func, argc);
rb_define_singleton_method(module, name, func, argc);
}
So, what does it mean that "system" is a method of Kernel's singleton class? Let's recap what happens when we create a class and add a method to the singleton class of one of it's instances.
class A
end
V1 = A.new # creates an instance of A and assign it to constant V1
V2 = A.new # ... and V2
# now we add method x() to V1's singleton class
class << V1
def x
puts "hello"
end
end
V1.x # will print "hello"
V2.x # will fail ... V2 does not have a method x()
Clear?
Ok, now, remember that all Ruby modules are instances of a class called Module? Say we replace A by Module, V1 by Kernel and x() by system(). What we get is the following:
Kernel = Module.new
class << Kernel
def system
...
end
end
And that's essentially what's going on behind the scenes.
Going back to the question that started this post, how do we remove a method from one of the built-in modules, anyway? The answer is easy, if not as obvious as we might have expected:
module Kernel
remove_method :system
end
class << Kernel
remove_method :system
end
Or, more concisely,
Kernel.send :remove_method, :system
class << Kernel; self; end.send :remove_method, :system
#remove system from module Kernel
Kernel.send :remove_method, :system
Well, not quite. While that prevents you from calling system() in the context of the current object, you can still invoke it like this:
Kernel::system('date')
What's going on?
It turns out that they way Kernel (and other built-in modules) are defined is analogous to doing the following:
module Kernel
def system (...)
...
end
module_function :system
end
Thus, system() is a method that will be added to instances of classes that include the given module (in our case, instances of any object, since Kernel is included by Object), but it is also a method in Kernel's singleton class (bear with me for a moment), or a module_method as the PickAxe book calls them. In Java parlance, they are simply static methods.
Looking at Ruby's source code, we can see that all of Kernel's methods are defined by way of the rb_define_module_function function, whose definition is:
void
rb_define_module_function(module, name, func, argc)
VALUE module;
const char *name;
VALUE (*func)();
int argc;
{
rb_define_private_method(module, name, func, argc);
rb_define_singleton_method(module, name, func, argc);
}
So, what does it mean that "system" is a method of Kernel's singleton class? Let's recap what happens when we create a class and add a method to the singleton class of one of it's instances.
class A
end
V1 = A.new # creates an instance of A and assign it to constant V1
V2 = A.new # ... and V2
# now we add method x() to V1's singleton class
class << V1
def x
puts "hello"
end
end
V1.x # will print "hello"
V2.x # will fail ... V2 does not have a method x()
Clear?
Ok, now, remember that all Ruby modules are instances of a class called Module? Say we replace A by Module, V1 by Kernel and x() by system(). What we get is the following:
Kernel = Module.new
class << Kernel
def system
...
end
end
And that's essentially what's going on behind the scenes.
Going back to the question that started this post, how do we remove a method from one of the built-in modules, anyway? The answer is easy, if not as obvious as we might have expected:
module Kernel
remove_method :system
end
class << Kernel
remove_method :system
end
Or, more concisely,
Kernel.send :remove_method, :system
class << Kernel; self; end.send :remove_method, :system
Labels: ruby
2 Comments:
Totally informative. You have a lovely style of explaining; thank you.
I don’t know If I said it already, but this so good stuff keep up the good work. I read a lot of blogs on a daily basis and for the most part Belajar seo blogspot just wanted to make a quick comment to say I’m glad I found your blog. Thanks.
Best regards
Seo Motivation Oes tsetnoc faq
Post a Comment
<< Home