如果在 Ruby 中使用 undef_method 取消定义 undef_method 会发生什么?

问题描述 投票:0回答:1

我刚刚了解到 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
1个回答
0
投票

Ruby 如何在未定义的情况下执行

undef_method

简单!

了解方法的工作原理可能会有所帮助。考虑

Kernel.puts(1 + 1)

按顺序发生的事情如下:

  1. 对接收器进行评估。
    • 这里,只是不断查找名字
      Kernel
  2. 对方法参数进行求值。
    • 因此,
      1 + 1
      结果为
      2
  3. 搜索接收方的方法表。
      找到
    • Kernel.puts
  4. 该方法被调用。
    • Kernel.puts
      使用参数
      2
      进行调用。
    • 出现副作用——打印“2”。
    • 返回值(
      nil
      )。

现在让我们以同样的方式看

Module.undef_method(:undef_method)

  1. 对接收器进行评估。
    • 再次,只是不断查找,这次是查找名称
      Module
  2. 对方法参数进行求值。
    • 参数只是符号文字
      :undef_method
      ,不需要额外的计算。
  3. 搜索接收方的方法表。
    • Module.undef_method
      已找到,因为它还没有发生任何事情。
  4. 该方法被调用。
    • Module.undef_method
      使用参数
      :undef_method
      进行调用。
    • 副作用发生了——它从接收者的方法表中删除了该方法。
    • 返回值(
      Module
      )。

正如你所看到的,这个“悖论”很容易解释,因为在查找方法时,该方法仍然存在。只有在查找并调用它之后,才会在单独的步骤中将其删除,并且从方法表中删除名称“undef_method”的行为不会影响已找到的方法完成执行的能力。

© www.soinside.com 2019 - 2024. All rights reserved.