我刚刚了解到 Ruby 有一个名为
undef_method
的特殊方法。
它实际上取消了现有方法的定义。
使用
undef_method
,您可以取消对 Integer 的 <
的定义,如下所示:
class Integer
undef_method :<
end
begin
puts 1 < 2
rescue Exception => exception
puts exception
puts 1.0 < 2
end
结果如下:
undefined method `<' for an instance of Integer
true
这是可以理解的,因为 Ruby 本身是高度面向对象的,一切都是对象,包括它的类型系统等等。
但是您可以取消定义
undef_method
,从而无法从 Integer 中取消定义 <
。
class Module
undef_method :undef_method
end
class Integer
undef_method :<
end
begin
puts 1 < 2
rescue Exception => exception
puts exception
puts 1.0 < 2
end
现在
undef_method
本身是未定义的,你不能真正从 Integer 中取消定义 <
。
temp.rb:6:in `<class:Integer>': undefined method `undef_method' for class Integer (NoMethodError)
undef_method :<
^^^^^^^^^^^^
from temp.rb:5:in `<main>'
所以问题是:当
undef_method
未定义时,Ruby 如何执行它?
如果 Ruby 是一种编译语言,我假设 Ruby 首先加载该方法并执行自定义代码,所以没问题! 但 Ruby 是解释性语言,在执行代码之前不会加载代码。
我认为这可能会导致问题,因为如果方法在执行时未定义,Ruby 无法判断要执行哪些代码。
Ruby 如何在未定义的情况下执行
?undef_method
简单!
了解方法的工作原理可能会有所帮助。考虑
Kernel.puts(1 + 1)
。
按顺序发生的事情如下:
Kernel
。1 + 1
结果为 2
。Kernel.puts
。Kernel.puts
使用参数 2
进行调用。nil
)。现在让我们以同样的方式看
Module.undef_method(:undef_method)
:
Module
。:undef_method
,不需要额外的计算。Module.undef_method
已找到,因为它还没有发生任何事情。Module.undef_method
使用参数 :undef_method
进行调用。Module
)。正如你所看到的,这个“悖论”很容易解释,因为在查找方法时,该方法仍然存在。只有在查找并调用它之后,才会在单独的步骤中将其删除,并且从方法表中删除名称“undef_method”的行为不会影响已找到的方法完成执行的能力。